package com.hsgene.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.SendResult;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hsgene.common.CaseType;
import com.hsgene.common.ClientType;
import com.hsgene.common.DeleteFlagType;
import com.hsgene.common.dto.CommonDictDto;
import com.hsgene.common.util.basic.JsonUtils;
import com.hsgene.common.util.basic.UUID32;
import com.hsgene.common.util.character.CharactersConstant;
import com.hsgene.common.util.date.SimpleDateUtils;
import com.hsgene.common.util.qiniu.QiniuCertificateUtil;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.common.util.result.NullObject;
import com.hsgene.common.util.result.PeanutApiResult;
import com.hsgene.common.util.support.LimitHelper;
import com.hsgene.common.util.support.OrderHelper;
import com.hsgene.common.util.support.Pagination;
import com.hsgene.common.util.validation.FieldChecker;
import com.hsgene.consumables.domain.v1.GeneticGoods;
import com.hsgene.consumables.domain.v1.GeneticGoodsApplyHistory;
import com.hsgene.dict.dto.SysDictDto;
import com.hsgene.generator.constants.GeneratorEnum;
import com.hsgene.generator.dto.GeneratorDto;
import com.hsgene.medicine.dto.DaCancerDto;
import com.hsgene.message.domain.PushInfo;
import com.hsgene.mq.DcwImageModel;
import com.hsgene.order.condition.GeneticTestingOrderCondition;
import com.hsgene.order.condition.GeneticTestingOrderField;
import com.hsgene.order.constants.PayType;
import com.hsgene.order.constants.PayerType;
import com.hsgene.order.constants.ReportAduitStatus;
import com.hsgene.order.constants.v1.*;
import com.hsgene.order.domain.OrderPackageDetail;
import com.hsgene.order.domain.billing.dto.OrderInvoiceInfoDto;
import com.hsgene.order.domain.disease.GeneOrder;
import com.hsgene.order.domain.reserve.CompleteOrderResultInfo;
import com.hsgene.order.domain.reserve.GeneticCompletePatientInfo;
import com.hsgene.order.domain.v1.*;
import com.hsgene.order.dto.OrderSumPriceCommission;
import com.hsgene.order.dto.SelectForInsertDoctorOrderModel;
import com.hsgene.order.dto.console.OrderUpdateRealPriceDto;
import com.hsgene.order.dto.console.SignDto;
import com.hsgene.order.dto.console.detail.OrderBaseInfo;
import com.hsgene.order.dto.doctor.*;
import com.hsgene.order.dto.peanut.*;
import com.hsgene.order.dto.v1.*;
import com.hsgene.order.exception.OrderErrorCode;
import com.hsgene.order.persistence.*;
import com.hsgene.order.service.OrderService;
import com.hsgene.order.service.UserAuthenticationService;
import com.hsgene.order.service.api.*;
import com.hsgene.product.domain.GeneticTestingPackage;
import com.hsgene.product.dto.peanut.GeneticTestingPackageDetilPeanutDto;
import com.hsgene.sample.dto.GeneticTestingSampleDto;
import com.hsgene.user.dto.user.GeneticTestingUserDto;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单ServiceImpl
 *
 * @author wangbing
 * @version 1.0, 2018/9/18
 */
@Service
public class OrderServiceImpl implements OrderService {

    private final static Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);

    // 订单创建半小时提示、一小时自动关闭
    private final static long ORDER_CREATION_NONE_PAID_TIME = 30 * 60 * 1000L;
    private final static long ORDER_AUTO_CLOSE_TIME = 60 * 60 * 1000L;

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private ConsoleOrderRepository consoleOrderRepository;

    @Resource
    private ExpressDeliveryRepository expressDeliveryRepository;

    @Resource
    private OrderPackageRepository orderPackageRepository;

    @Resource
    private OrderPaymentRepository orderPaymentRepository;

    @Resource
    private GeneratorService generatorService;

    @Resource
    private ReserveOrderRepository reserveOrderRepository;

    @Resource
    private AgencyOrderRepository agencyOrderRepository;

    @Resource
    private ConsumablesGoodsService consumablesGoodsService;

    @Resource
    private ProductService productService;

    @Resource
    private AgencyApplyOrderService agencyApplyOrderService;

    @Resource
    private OrderRequisitionRepository orderRequisitionRepository;

    @Resource
    private OrderInterchangeRepository orderInterchangeRepository;

    @Resource
    private MedicineService medicineService;

    @Resource
    private GeneticUserService geneticUserService;

    @Resource
    private DictService dictService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private SampleService sampleService;
    @Resource
    private OrderPackageDetailMapper orderPackageDetailMapper;

    @Resource
    private InvoiceOpenRepository invoiceOpenRepository;

    @Resource
    private MqService mqService;

    @Resource
    private UserAuthenticationService userService;

    @Resource
    private Producer producer;

    @Resource
    private NotificationService notificationService;

    @Value("${payment.domain}")
    private String paymentDomain;

    @Value("${genetic.testing.orders.report.domain}")
    private String reportDomain;

    @Value("${genetic.testing.orders.report.cache.key}")
    private String reportCacheKey;

    @Value("${genetic.testing.orders.report.cache.expire}")
    private int reportCacheExpireSeconds;

    @Value("${genetic.testing.orders.dcw.warn.limit}")
    private long needWarnRequestedLimit;

    @Value("${send.point.tag}")
    private String verifyIntegralTag;

    @Value("${mq.apply}")
    private String applyTag;

    @Value("${mq.rocket.topic.genetic_testing_order}")
    private String orderMQTopic;

    @Value("${mq.rocket.tag.genetic_testing_order_none_paid}")
    private String orderNonePaidMQTag;

    @Value("${mq.rocket.tag.genetic_testing_order_auto_close}")
    private String orderAutoCloseMQTag;


    private Map<String, Function<ClientType, List<CommonDictDto>>> orderDictQueryHandleMap = Maps.newHashMap();

    @PostConstruct
    private void initDictQueryHandleMap() {
        orderDictQueryHandleMap.put("order_status", v -> queryOrderStatus(v));
        orderDictQueryHandleMap.put("express_company", v -> querySupportedExpressCompany(v));
        orderDictQueryHandleMap.put("molecule_test_purpose", v -> queryMoleculeTestPurpose(v));
        orderDictQueryHandleMap.put("gene_case_type", v -> queryGeneCaseType(v));
    }

    /**
     * @param orderId 订单id
     * @return int
     * @description 获取患者信息确认状态
     * @author maodi
     * @createDate 2018/10/31 9:18
     */
    @Override
    public Integer getPatientInfoConfirm(String orderId) {
        return orderRepository.getPatientInfoConfirm(orderId);
    }

    @Override
    public ApiResult<Pagination<PeanutOrderItemDto>> queryServantTestingOrder(
            GeneticTestingOrderCondition condition, OrderHelper orderHelper, LimitHelper limitHelper) {
        FieldChecker.checkEmpty(limitHelper, "分页参数");
        if (orderHelper != null) {
            orderHelper.validate(GeneticTestingOrderField.getInstance());
        }
        int totalCount = orderRepository.getConditionCount(condition);
        Pagination<PeanutOrderItemDto> pagination = Pagination.newInstance(limitHelper, totalCount);
        if (totalCount > 0) {
            List<TestingOrderDto> list = orderRepository.queryConditionOrder(condition, orderHelper, limitHelper);
            List<PeanutOrderItemDto> result = wrapTestingOrders(list);
            pagination.setResult(result);
        }
        return ApiResult.succ(pagination);
    }

    /**
     * 完善医生订单信息
     *
     * @param orderInfo  订单完善信息
     * @param updateTime 完善时间
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public ApiResult completeOrder(ReserveOrderCompleteInfo orderInfo, Date updateTime) {
        String newOrderNo = orderInfo.getOrderNo();
        String oldOrderId = orderInfo.getOrderId();
        //判断订单来源:因子网PC，因子网小程序，因子网APP，确认订单后，状态为待地管确认
        Integer status = OrderStatus.DIFU_CONFIRMED.getCode();
        String newOrderId = getUUID32();
        //订单信息
        ApiResult result = inserNewOrderInfo(orderInfo, updateTime, newOrderNo, newOrderId, status, oldOrderId);
        if (result.isSucc()) {
            //TODO 小程序端部分数据不可变，直接数据库取出更新到新订单
            if (StringUtils.isNotEmpty(oldOrderId)) {
                Map<String, Object> map = orderRepository.getAppOrderInfo(oldOrderId);
                //更新
                orderRepository.updateAppOrderInfo(map, newOrderId);
            }
            //TODO 由于比较旧数据比较繁琐,故旧数据逻辑删除,完善信息直接新增
            orderRepository.deleteOldOrder(oldOrderId, updateTime);
            //删除医生记录
            orderRepository.deleteDoctorOldOrder(oldOrderId, updateTime);

        }
        return result;
    }

    private ApiResult inserNewOrderInfo(DifuCreateOrderInfoDto orderInfo, Date updateTime, String newOrderNo, String
            newOrderId, int status, String oldOrderId) {
        //如果是小程序来的订单则不校验，因为小程序的有优惠
        if (!orderInfo.getPlatform().equals(ClientType.APPLETS.getCode())) {
            for (OrderCompleteProductInfo product : orderInfo.getProductInfoList()) {
                //判断套餐费用与数据库是否一致
                String packId = product.getPackageId();
                Double dataMoney = orderRepository.getPackPrice(packId);
                if (dataMoney == null || product.getFee() != dataMoney) {
                    return ApiResult.fail(OrderErrorCode.PACKAGE_PRICE_IS_ERROR, "套餐真实价格是：" + dataMoney);
                }
                BigDecimal cost = orderRepository.packageCost(product.getPackageId(), product.getAgencyId());
                product.setCost(cost);
            }
        }
        //校验样本条码是否重复
        List<OrderCompleteProductInfo> productInfoList = orderInfo.getProductInfoList();
        List<String> newPackageList = new ArrayList<>();
        for (OrderCompleteProductInfo productInfo : productInfoList) {
            String sampleCode = productInfo.getSampleBarCode();
            //排除当前订单外，样本编码重复的订单
            Integer exist = orderRepository.checkSampleBarCodeIsExists(sampleCode, oldOrderId);
            if (exist != null) {
                return ApiResult.failFormatTip(OrderErrorCode.SAMPLE_BARCODE_IS_EXISTS, sampleCode);
            }
            newPackageList.add(productInfo.getPackageId());
        }
        //获取新订单套餐总金额、佣金
        OrderSumPriceCommission newPrice = reserveOrderRepository.getProductSumPrice(newPackageList);
        if (newPrice == null || newPrice.getTotalCharges() == 0) {
            return ApiResult.fail(OrderErrorCode.PRODUCT_IS_NOT_EXIST);
        }
        //不是金琉璃的订单，则需要查询医生信息
        String doctorName = null;
        String doctorPhone = null;
        if (!orderInfo.getPlatform().equals(ClientType.GOLD_COLORED_GLASS.getCode())) {
            Map<String, Object> doctorMap = userService.userAuthVerify(orderInfo.getDoctorId());
            if (doctorMap == null || doctorMap.isEmpty()) {
                return ApiResult.fail(OrderErrorCode.DOCOTOR_ID_IS_NOT_EXIST);
            }
            doctorName = (String) doctorMap.get("name");
            doctorPhone = (String) doctorMap.get("phone");
        }
        //订单创建时间不可变
        Date createTime = oldOrderId == null ? updateTime : orderRepository.getOrderCreateTime(oldOrderId);
        //判断是否是补全订单操作
        Double oldPrice = checkIsExistsOldOrder(orderInfo, updateTime, newOrderId, oldOrderId, newPackageList,
                newPrice);
        //订单总价不应该变
        newPrice.setTotalCharges(oldPrice);
        Integer payerType = orderInfo.getPayerType();
        GeneticCompletePatientInfo patientInfo = orderInfo.getPatientInfo();
        //插入主订单表中新信息(患者信息、用户姓名、检测目的)
        orderRepository.updateMainTestingOrder(newOrderId, newOrderNo, orderInfo, patientInfo, createTime, updateTime,
                status, newPrice, 0, doctorName, doctorPhone);
        //插入数据
        insertOrderInfoToDB(orderInfo, createTime, updateTime, newOrderId, oldPrice, payerType, oldOrderId);
        String caseType = orderInfo.getCaseType();
        List<String> packageIdList = new ArrayList<>();
        for (OrderCompleteProductInfo productInfo : productInfoList) {
            packageIdList.add(productInfo.getPackageId());
        }
        //计算订单地服和医生经验值
        calculateVal(packageIdList, caseType, newOrderId);
        //套餐被用标记
        updatePackageUseInfo(newPackageList);
        //更新genetic_order_operation_detail、genetic_testing_order_payment中的orderId
        if (oldOrderId != null) {
            LOGGER.info("update operation detail,oldOrderId:" + oldOrderId + ",newOrderId:" + newOrderId);
            //更新操作记录表
            orderRepository.updateOperationDetail(oldOrderId, newOrderId);
            LOGGER.info("update payment info,oldOrderId:" + oldOrderId + ",newOrderId:" + newOrderId);
            //更新支付记录表
            orderRepository.updatePayment(oldOrderId, newOrderId);
            //更新dcw表订单id数据
            orderRepository.updateOrderDcw(newOrderId, oldOrderId);
            //更新dcw rollback表订单id数据
            orderRepository.updateOrderDcwRollback(newOrderId, oldOrderId);
        }
        CompleteOrderResultInfo resultInfo = new CompleteOrderResultInfo(newOrderId, newOrderNo, (float) newPrice
                .getTotalCharges(), orderInfo.getUserId());
        return ApiResult.succ(resultInfo, "下单成功");
    }

    /**
     * 补全订单判断
     *
     * @param orderInfo      订单信息
     * @param updateTime     时间
     * @param newOrderId     新订单id
     * @param oldOrderId     旧订单id
     * @param newPackageList 套餐
     * @param newPrice       新订单价格
     * @return
     */
    private Double checkIsExistsOldOrder(DifuCreateOrderInfoDto orderInfo, Date updateTime, String newOrderId, String
            oldOrderId, List<String> newPackageList, OrderSumPriceCommission newPrice) {
        //oldOrderId不为空，说明是补全订单,为空，说明是地服创建订单
        if (StringUtils.isEmpty(oldOrderId)) {
            return newPrice.getTotalCharges();
        }
        //数据库订单旧价格
        Double oldPrice = orderRepository.getOldOrderPrice(oldOrderId);
        //差价
        Double differencePrices = newPrice.getTotalCharges() - oldPrice;
        //genetic_testing_order_interchange记录旧订单-新订单更换历史
        updateRecordHistory(orderInfo, updateTime, newOrderId, oldOrderId, newPackageList, differencePrices);
        return oldPrice;
    }

    /**
     * 插入数据
     *
     * @param orderInfo  订单信息
     * @param createTime 创建时间
     * @param updateTime 时间
     * @param newOrderId 新订单ID
     * @param oldPrice   旧价格
     * @param payerType  支付类型
     * @param oldOrderId
     */
    private void insertOrderInfoToDB(DifuCreateOrderInfoDto orderInfo, Date createTime, Date updateTime, String
            newOrderId, Double oldPrice, Integer payerType, String oldOrderId) {
        //获取疾病id
        String diseaseIds = orderInfo.getDiseaseList().stream()
                .map(GeneticCompleteDisease::getId)
                .collect(Collectors.joining(CharactersConstant.COMMA_SEMICOLON));
        String diseaseNames = orderInfo.getDiseaseList().stream()
                .map(GeneticCompleteDisease::getDiseaseName)
                .collect(Collectors.joining(CharactersConstant.COMMA_SEMICOLON));
        //订单A表信息插入
        Integer orderCount = orderRepository.getCountAByOrderId(oldOrderId);
        if (orderCount > 0) {
            orderRepository.updateOrderAddtionA(newOrderId, orderInfo.getClinicalDiagnosis(), orderInfo.getUserId(),
                    createTime, updateTime, diseaseIds, diseaseNames, oldOrderId);
        } else {
            orderRepository.inserOrderA(newOrderId, orderInfo.getClinicalDiagnosis(), orderInfo.getUserId(),
                    createTime, updateTime, diseaseIds, diseaseNames);
        }
        //订单B表数据插入
        if (StringUtils.isEmpty(oldOrderId)) {
            orderRepository.inserOrderB(newOrderId, oldPrice, orderInfo.getPatientInfo(), payerType);
        } else {
            orderRepository.updateOrderB(newOrderId, oldPrice, orderInfo.getPatientInfo(), payerType, oldOrderId);
        }
        //判断是否存在genetic_testing_order_dcw
        UploadDcwDetailsDto exists = orderRepository.getDcwInfoByOrderId(oldOrderId);
        if (exists != null) {
            //更新病例类型
            orderRepository.updateDcwType(newOrderId, orderInfo.getCaseType(), oldOrderId);
        } else {
            //插入病例类型
            orderRepository.insertDcwType(newOrderId, orderInfo.getCaseType());
        }
        //插入订单套餐表genetic_testing_order_package信息
        orderRepository.inserOrderPackage(newOrderId, orderInfo.getProductInfoList());
        //插入使用耗材信息genetic_testing_goods_consume
        List<GeneticOrderGoodsInfoDto> goodsInfoList = orderInfo.getGoodsInfoList();
        if (goodsInfoList != null && !goodsInfoList.isEmpty()) {
            orderRepository.insertOrderGoodsConsume(goodsInfoList, newOrderId, updateTime);
        }
        //金琉璃、花生仁订单插入发票表数据
        if (orderInfo.getPlatform().equals(ClientType.PEANUT.getCode()) || orderInfo.getPlatform().equals(ClientType
                .GOLD_COLORED_GLASS.getCode())) {
            OrderInvoiceInfoDto invoiceInfo = new OrderInvoiceInfoDto();
            invoiceInfo.setOrderId(newOrderId);
            invoiceInfo.setInvoiceMoney(oldPrice);
            invoiceInfo.setInvoiceName(orderInfo.getPatientInfo().getPatientName());
            invoiceInfo.setInvoiceId(UUID32.randomUUIDString());
            invoiceOpenRepository.inserInvoiceInfo(invoiceInfo);
        }
    }

    /**
     * 修改历史记录
     *
     * @param orderInfo        订单信息
     * @param updateTime       时间
     * @param newOrderId       新订单id
     * @param oldOrderId       旧订单id
     * @param newPackageList   套餐id
     * @param differencePrices 差价
     */
    private void updateRecordHistory(DifuCreateOrderInfoDto orderInfo, Date updateTime, String newOrderId, String
            oldOrderId, List<String> newPackageList, Double differencePrices) {
        //变更编号
        String recordNo = getOrderNo(GeneratorEnum.TCBG.getType());
        //获取旧订单套餐ID
        String oldPackageIds = orderRepository.getOldPackageIds(oldOrderId);
        String newPackageIds = Joiner.on(CharactersConstant.COMMA_EN).join(newPackageList);
        orderRepository.recordChangeHistory(getUUID32(), oldOrderId, newOrderId, oldPackageIds, newPackageIds,
                differencePrices, updateTime, orderInfo.getPayerType(), orderInfo.getImages(), "地服人员完善订单信息", recordNo);
        List<SelectForInsertDoctorOrderModel> models = orderRepository.selectForInsertDoctorOrder(newPackageList);
        SelectForInsertDoctorOrderModel model = new SelectForInsertDoctorOrderModel();
        models.forEach(e -> {
            if (StringUtils.isBlank(model.getCancerId())) {
                model.setCancerId(e.getCancerId());
            } else {
                model.setCancerId(model.getCancerId() + "," + e.getCancerId());
            }
            if (StringUtils.isBlank(model.getDrugName())) {
                model.setDrugName(e.getDrugName());
            } else {
                model.setDrugName(model.getDrugName() + "," + e.getDrugName());
            }
            if (StringUtils.isBlank(model.getGeneticLocus())) {
                model.setGeneticLocus(e.getGeneticLocus());
            } else {
                model.setGeneticLocus(model.getGeneticLocus() + "," + e.getGeneticLocus());
            }
            if (StringUtils.isBlank(model.getSampleType())) {
                model.setSampleType(e.getSampleType());
            } else {
                model.setSampleType(model.getSampleType() + "," + e.getSampleType());
            }
            if (StringUtils.isBlank(model.getTherapyType())) {
                model.setTherapyType(e.getTherapyType());
            } else {
                model.setTherapyType(model.getTherapyType() + "," + e.getTherapyType());
            }
        });
        model.trim();
        //信息完善完成之后,插入新记录到医生订单表
        orderRepository.inserDoctorOrder(newOrderId, orderInfo.getRemarks(), newPackageList, updateTime, newPackageIds, model);
    }

    /**
     * 地服创建订单
     *
     * @param orderInfo  订单信息
     * @param updateTime 时间
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public ApiResult createOrder(DifuCreateOrderInfoDto orderInfo, Date updateTime) {
        String newOrderNo = getOrderNo(GeneratorEnum.MEDI.getType());
        String newOrderId = getUUID32();
        return inserNewOrderInfo(orderInfo, updateTime, newOrderNo, newOrderId, OrderStatus.WAIT_RECEIPT_MONEY
                .getCode(), null);
    }

    /**
     * 套餐占用标记
     *
     * @param newPackageList
     */
    private void updatePackageUseInfo(List<String> newPackageList) {
        //标记套餐被使用
        productService.tagPackage(newPackageList);
        for (String packageId : newPackageList) {
            /*GeneticTestingPackage testingPackage = new GeneticTestingPackage();
            testingPackage.setId(packageId);
            testingPackage.setIsUsed(1);*/
            //更新购买数
            orderRepository.updatePackageBuyCount(packageId, 1);
            // productService.updateProduct(testingPackage);
        }
    }

    /**
     * 线下付款弹窗信息
     *
     * @param id 订单id
     * @return
     */
    @Override
    public ApiResult underLinePaymentInfo(String id) {
        TestingOrderDto testingOrderDto = orderRepository.underLinePaymentInfo(id);
        return new ApiResult(200, "success", "获取线下付款弹窗信息成功", testingOrderDto);
    }

    /**
     * 保存线下收款填写的信息并更改订单状态
     *
     * @param geneticTestingOrderAddtionB
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public ApiResult updateTestingOrder(GeneticTestingOrderAddtionB geneticTestingOrderAddtionB) {
        //将订单状态改为“地服收款完成”
        orderRepository.updateTestingOrderStatus(geneticTestingOrderAddtionB.getGeneticTestingOrderId(), 5, new Date());
        orderRepository.updateTestingOrderAddTionB(geneticTestingOrderAddtionB);
        return new ApiResult(200, "success", "保存成功", null);
    }

    /**
     * 地服完善信息
     *
     * @param difuCompete 完善信息对象
     * @param userId
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public String difuComplete(DifuCompeteOrderInfoDto difuCompete, String userId) {
        String orderId = difuCompete.getOrderId();
        Date updateTime = new Date();
        //更新genetic_testing_order_package表中快递信息
        orderRepository.updateOrderPackageExpress(difuCompete.getExpressDeliveryInfo(), orderId);
        //更新表genetic_testing_order中样本图片、快递图片地址
        orderRepository.updateOrderSampleImages(orderId, difuCompete.getSampleImages(), difuCompete
                .getExpressReturnImages(), updateTime);
        List<GeneticOrderGoodsInfoDto> goodsInfoDtos = difuCompete.getProductInfoList();
        if (goodsInfoDtos == null || goodsInfoDtos.isEmpty()) {
            return null;
        }
        for (GeneticOrderGoodsInfoDto goodsInfo : goodsInfoDtos) {
            //获取库存数量
            Integer amount = orderRepository.getGoodsAmount(goodsInfo.getGoodsId());
            if (amount == null) {
                return "耗材不存在";
            }
            if (goodsInfo.getUsageAmount() > amount) {
                return "使用量不能大于库存量";
            }
        }
        /**
         * 耗材变动包含:创建订单选择耗材与完善时选用耗材不一致时,
         * 逻辑删除旧数据,插入新数据
         */
        List<String> oldConsumableIdLists = orderRepository.getOldConsumables(orderId);
        if (oldConsumableIdLists == null || oldConsumableIdLists.isEmpty()) {
            //直接插入耗材
            orderRepository.insertOrderGoodsConsume(goodsInfoDtos, orderId, updateTime);
            return null;
        }
        //删除旧数据
        orderRepository.deleteOldConsumableInfo(oldConsumableIdLists, difuCompete.getOrderId(), updateTime);
        //插入新耗材
        orderRepository.insertOrderGoodsConsume(goodsInfoDtos, orderId, updateTime);
        //更新申请历史genetic_goods_apply_history表
        orderRepository.updateGoodsApplyHistory(goodsInfoDtos, userId, updateTime);
        return null;
        //校验旧耗材ID,并删除不在使用的旧耗材信息
        //checkOldConsumableId(difuCompete, oldConsumableIdLists, updateTime);
    }

    /**
     * @param id           订单id
     * @param cancelReason 取消原因
     * @param cancelType   取消类型
     * @return void
     * @description 取消基因检测单
     * @author maodi
     * @createDate 2018/9/29 10:06
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public void cancelOrder(String id, String cancelReason, Integer cancelType) {
        Date updateDateTime = new Date();
        OrderBaseInfo orderBaseInfo = consoleOrderRepository.orderDetail(id);
        Integer status = orderBaseInfo.getStatus();
        orderRepository.updateBeforeExceptionStatus(status, updateDateTime, id);
        orderRepository.cancelTestingOrder(id, cancelReason, cancelType, updateDateTime);
        orderRepository.cancelTestingOrderAddtionA(id, updateDateTime);
    }


    /**
     * 计算佣金
     *
     * @param paramDto 参数
     * @return
     */
    @Override
    public OrderCommissionInfo calculateCommission(CalculateCommissionParamDto paramDto) {
        //获取计算比例
        return orderRepository.calculateCommission(paramDto);
    }

    /**
     * @param orderId 订单id
     * @return com.hsgene.order.dto.peanut.BaseInfoDataDto
     * @description 获取基因检测单基础信息
     * @author maodi
     * @createDate 2018/9/29 15:27
     */
    @Override
    public BaseInfoDataDto getBaseInfoById(String orderId) {
        BaseInfoDataDto baseInfo = orderRepository.getBaseInfoById(orderId);
        if(baseInfo.getFee() == null) {
            baseInfo.setFee(0d);
        }
        if (baseInfo.getTotalCharges() == null) {
            baseInfo.setTotalCharges(0d);
        }
        if (baseInfo.getPayAmount() == null) {
            baseInfo.setPayAmount(0d);
        }
        long currentTime = System.currentTimeMillis();
        long createDateTime = baseInfo.getCreateDate().getTime();
        long countDown = (3600000 + createDateTime) - currentTime;
        if (countDown < 0) {
            countDown = 0;
        }
        countDown = countDown / 1000;
        GeneOrderRelationDto geneOrderRelation = new GeneOrderRelationDto();
        geneOrderRelation.setPayerType(baseInfo.getPayerType());
        geneOrderRelation.setTestingApplyType(baseInfo.getTestingApplyType());
        geneOrderRelation.setId(baseInfo.getbId());
        baseInfo.setGeneOrderRelation(geneOrderRelation);
        baseInfo.setRemindSeconds(countDown);
        return baseInfo;
    }

    /**
     * 同步检测单信息
     * (注意:套餐数据变动时:套餐ID不变)
     *
     * @param orderId 检测单ID
     */
    @Override
    public void synTestOrder(String orderId) {
        Date updateTime = new Date();
        //根据订单ID获取当前套餐检测信息和患者信息
        List<GeneRequisitionData> requisitionDataList = orderRepository.getTestRequisitionDataByOrderId(orderId);
        if (requisitionDataList == null || requisitionDataList.isEmpty()) {
            return;
        }
        requisitionDataList.stream().forEach(requisitionData -> {
            orderRepository.updateTestRequisitionData(orderId, requisitionData.getOrgId(), JSON.toJSONString
                    (requisitionData), updateTime);
        });
    }

    /**
     * 上传dcw
     *
     * @param testingOrder dcw信息
     */
    @Override
    public ApiResult uploadDcw(UploadDcwDetailsDto testingOrder) {
        //校验订单是否存在
        Boolean flag = orderRepository.orderIsExists("genetic_testing_order", "id", testingOrder.getOrderId());
        if (flag == null || !flag) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        //判断是否存在genetic_testing_order_dcw
        UploadDcwDetailsDto exists = orderRepository.getDcwInfoByOrderId(testingOrder.getOrderId());
        if (exists != null) {
            //更新dcw信息
            orderRepository.updateDcwInfo(testingOrder, new Date());
        } else {
            //插入dcw信息
            testingOrder.setId(UUID32.randomUUIDString());
            orderRepository.insertDcwInfo(testingOrder, new Date());
        }
        return ApiResult.succ(null, "dcw上传成功");
    }

    /**
     * 申请录入
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public ApiResult applicationEntry(String orderId) {
        //校验订单是否存在
        Boolean flag = orderRepository.orderIsExists("genetic_testing_order", "id", orderId);
        if (flag == null || !flag) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        //校验是否上传dcw
        Boolean dcwFlag = orderRepository.orderIsExists("genetic_testing_order_dcw", "genetic_testing_order_id",
                orderId);
        if (dcwFlag == null || !dcwFlag) {
            return ApiResult.fail(OrderErrorCode.DCW_IS_NOT_NULL);
        }
        //调用消息队列,申请录入
        Map<String, Object> map = orderRepository.getSendPointInfo(orderId);
        if (map == null || map.isEmpty()) {
            return ApiResult.fail(OrderErrorCode.DIFI_INFO_NOT_EXISTS);
        }
        LOGGER.info("apply info is:" + map);
        //申请录入不需要总价、经验值
        map.remove("totalCharges");
        map.remove("totalCommission");
        map.put("tagType", applyTag);
        ApiResult sendResult = mqService.sendMQ(map);
        if (!sendResult.isSucc()) {
            LOGGER.error("申请录入失败...");
            return ApiResult.fail(OrderErrorCode.ENTRY_IS_ERROR);
        }
        orderRepository.updateDcwEntry(orderId);
        return ApiResult.succ(null, "申请录入请求成功");
    }

    /**
     * 确认签收
     *
     * @param receiptDto 确认签收的信息
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    public ApiResult confirmReceipt(OrderConfirmReceiptDto receiptDto) {
        String orderId = receiptDto.getOrderId();
        //校验订单是否存在
        Boolean orderflag = orderRepository.orderIsExists("genetic_testing_order", "id", orderId);
        if (orderflag == null || !orderflag) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        //更新快递信息为已确认confirmed状态
        orderRepository.updateExpressDelivery(receiptDto.getExpressImgs(), orderId, receiptDto.getExpressIds());
        //校验该订单是否还有余下物流未完成,若没有,则更新总订单完成
        Boolean flag = orderRepository.getExpressDelivery(orderId);
        if (flag != null && flag) {
            return ApiResult.succ(null, "确认签收成功");
        }
        Integer isLastSign = receiptDto.getIsLastSign();
        if (isLastSign == null) {
            return ApiResult.fail(OrderErrorCode.IS_LAST_SIGN_IS_NOT_NULL);
        }
        if (isLastSign != 0 && isLastSign != 1) {
            return ApiResult.fail(OrderErrorCode.IS_LAST_SIGN_IS_ERROR);
        }
        Integer platform = receiptDto.getPlatform();
        if (platform == null) {
            return ApiResult.fail(OrderErrorCode.PLATFORM_IS_NOT_NULL);
        }
        if (ClientType.CONSOLE.getCode().equals(platform) && ClientType.PEANUT.getCode().equals(platform) &&
            ClientType.GOLD_COLORED_GLASS.getCode().equals(platform) && ClientType.APPLETS.equals(platform) &&
            ClientType.APP.getCode().equals(platform)) {
            return ApiResult.fail(OrderErrorCode.PLATFORM_IS_ERROR);
        }
        Integer orderOrigin = orderRepository.queryOrderOrigin(orderId);
        //如果勾选状态为最后一次签收，订单来源为商城以外的，订单状态改为完成。订单来自商城的，订单状态变为待发货
        if (isLastSign == 1) {
            if (ClientType.CONSOLE.getCode().equals(orderOrigin) || ClientType.PEANUT.getCode().equals(orderOrigin) ||
                ClientType.GOLD_COLORED_GLASS.getCode().equals(orderOrigin)) {
                orderRepository.updateMainOrderFinished(orderId, new Date());
            } else {
                orderRepository.updateMainOrderDelivery(orderId, new Date());
            }
        }
        //如不勾选，订单状态不变
        return ApiResult.succ(null, "订单完成，确认签收成功");
    }

    /**
     * 地服（花生仁以前叫确认报告）
     *
     * @param orderPackageDetail
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public ApiResult updateReportStatus(OrderPackageDetail orderPackageDetail) {
        //报告审核时，判断订单信息是否完善
        GeneticTestingOrderPackage orderPackage = orderPackageRepository.findOrderPackage(orderPackageDetail
                .getGeneticTestingOrderId(), orderPackageDetail.getPackageId());
        ApiResult<List<GeneticTestingSampleDto>> samplesByIds = sampleService.getSamplesByIds(orderPackage
                .getSampleIds());
        if (!samplesByIds.isSucc()) {
            return ApiResult.fail(samplesByIds.getError());
        }
        if(samplesByIds.getData()!=null){
            boolean b = samplesByIds.getData().stream().filter(c->c.getLabelKey()!=null).anyMatch(c -> c.getLabelKey().contains("5"));
            if (b) {
                //样本图片、快递回单为空,展示完善按钮
                //耗材信息不存在,展示完善按钮
                OrderCheckInfoDto result = orderRepository.checkOrderSample(orderPackageDetail.getGeneticTestingOrderId());
                if (result == null || StringUtils.isEmpty(result.getExpressImages()) || StringUtils.isEmpty(result
                        .getSampleImages()) || result.getGoodsConsumes() == null || result.getGoodsConsumes().isEmpty()) {
                    LOGGER.error("goods consumes order info is not complete", new IllegalArgumentException());
                    return ApiResult.failFormatTip(OrderErrorCode.ORDER_IS_NOT_COMPLETED, "耗材信息");
                }
            }
        }
        //套餐物流为空,展示完善按钮
        OrderCheckInfoDto checkInfoDto = orderRepository.checkPackageDeliver(orderPackageDetail
                .getGeneticTestingOrderId());
        List<GeneticTestingExpressDeliveryDto> deliveryDtos = checkInfoDto.getDeliveryDtos();
        if (deliveryDtos == null) {
            LOGGER.error("deliveryDtos order info is not complete", new IllegalArgumentException());
            return ApiResult.failFormatTip(OrderErrorCode.ORDER_IS_NOT_COMPLETED, "套餐物流");
        }
        for (GeneticTestingExpressDeliveryDto deliveryDto : deliveryDtos) {
            if (deliveryDto.getExpressCompany() == null || deliveryDto.getRemarks() == null || deliveryDto
                    .getCourierDateTime() == null) {
                LOGGER.error("deliveryDto order info is not complete", new IllegalArgumentException());
                return ApiResult.failFormatTip(OrderErrorCode.ORDER_IS_NOT_COMPLETED, "物流信息");
            }
        }
      /*  if (checkOrderPackageInfo(orderPackageDetail.getGeneticTestingOrderId())) {
            LOGGER.error("order info is not complete");
            return ApiResult.fail(OrderErrorCode.ORDER_INFO_IS_NOT_COMPLETE);
        }*/

        if (ReportAduitStatus.getEnum(orderPackageDetail.getReportAuditFlag()).equals(ReportAduitStatus.UNDEFINED)) {
            return ApiResult.fail(OrderErrorCode.WRONG_STATE_VALUE);
        }
        if (ReportAduitStatus.DIDNOTPASS.getCode() == orderPackageDetail.getReportAuditFlag() && StringUtils.isEmpty
                (orderPackageDetail.getReportAuditRejectReason())) {
            return ApiResult.fail(OrderErrorCode.CANNOT_BE_EMPTY_IF_NOT);
        }
        //更新detail报告审核状态
        orderRepository.updateReportStatus(orderPackageDetail);
        //根据订单id和套餐id，修改package 的报告状态
        //如果审核通过修改为报告待寄送，否则修改为报告待上传
        if (ReportAduitStatus.PASS.getCode() == orderPackageDetail.getReportAuditFlag()) {
            orderRepository.updateOrderPackageStatus(orderPackageDetail, 4);
        } else if (ReportAduitStatus.DIDNOTPASS.getCode() == orderPackageDetail.getReportAuditFlag()) {
            orderRepository.updateOrderPackageStatus(orderPackageDetail, 2);
        }
        List<OrderPackageDetail> orderPackageDetails = orderPackageDetailMapper.getDetailByOrderId(orderPackageDetail
                .getGeneticTestingOrderId());
        //检查是否是订单下所有的报告都已经审核了且通过，如果是，更改订单状态。true-不改订单状态
        //如果报告全部已审核需要根据报告状态更新订单很状态
        long count = orderPackageDetails.stream().filter(c -> c.getReportAuditFlag() != null).count();
        //已全部审核
        if (orderPackageDetails.size() == count) {
            List<Integer> collect = orderPackageDetails.stream().map(OrderPackageDetail::getReportAuditFlag).distinct
                    ().collect(Collectors.toList());
            if (collect.size() == 1) {
                if (ReportAduitStatus.PASS.getCode() == collect.get(0)) {
                    orderRepository.updateTestingOrderStatus(orderPackageDetail.getGeneticTestingOrderId(), OrderStatus
                            .PENDING_PAYMENT.getCode(), new Date());
                } else if (ReportAduitStatus.DIDNOTPASS.getCode() == collect.get(0)) {
                    orderRepository.updateTestingOrderStatus(orderPackageDetail.getGeneticTestingOrderId(), OrderStatus
                            .TESTING.getCode(), new Date());
                }
            }
        }
        return ApiResult.succ();
    }

    /**
     * 根据id获取检测申请单信息（花生仁）
     *
     * @param requistionId 申请单id
     * @return
     */
    @Override
    public ApiResult requistions(String requistionId) {
        PeanutOrderRequisitionDto peanutOrderRequisitionDto = agencyOrderRepository.requistions(requistionId);
        if (peanutOrderRequisitionDto.getRequisitionData() != null) {
            peanutOrderRequisitionDto.getRequisitionData().setPatientSexDesc(SexType.sex(peanutOrderRequisitionDto
                    .getRequisitionData().getPatientSex()));
        }
        return new ApiResult(200, "success", "数据获取成功", peanutOrderRequisitionDto);
    }

    private String getOrderNo(String type) {
        ApiResult<GeneratorDto> generatorResult = generatorService.numberGenerator(type, 0, 0);
        if (generatorResult.isSucc()) {
            return generatorResult.getData().getSerialNumber();
        }
        return getUUID32();
    }

    private String getUUID32() {
        return UUID32.randomUUIDString();
    }

    private List<PeanutOrderItemDto> wrapTestingOrders(List<TestingOrderDto> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.parallelStream().map(order -> {
            PeanutOrderItemDto item = new PeanutOrderItemDto();
            BeanUtils.copyProperties(order, item);
            OrderStatus status = OrderStatus.getEnum(order.getStatus());
            item.setFirstSingleAward(order.getFirstSingleAward());
            item.setStatus(String.valueOf(status.getCode()));
            item.setStatusDictLabel(status.getDesc());
            item.setHasDcw(checkHasDcw(order));
            item.setNeedConfirmRecieved(checkNeedConfirmRecieved(order));
            item.setNeedWarnRequested(checkNeedWarnRequested(order));
            item.setNeedSupplyExpress(needSupplyExpress(order));
            wrapOrderPayment(item, order);
            // 填充DCW相关标志位
            item.setRequested(checkRequested(order));
            // 判断订单是否已关闭
            item.setIsClosed(status.isClosed() ? 1 : 0);
            //状态下显示完善按钮：2-待地管确认、7-待确认样本、9-报告待上传、20-报告待审核状态
            //报告待审核状态有条件显示
            Boolean flag = status == OrderStatus.PAID_FOR ? checkOrderPackageInfo(order.getId()) : status
                    .canShowCompleteBtn();
            item.setCanShowCompleteBtn(flag);
            return item;
        }).collect(Collectors.toList());
    }

    private boolean checkOrderPackageInfo(String orderId) {
        //样本图片、快递回单为空,展示完善按钮
        //耗材信息不存在,展示完善按钮
        OrderCheckInfoDto result = orderRepository.checkOrderSample(orderId);
        if (result == null || StringUtils.isEmpty(result.getExpressImages()) ||
            StringUtils.isEmpty(result.getSampleImages()) || result.getGoodsConsumes() == null
            || result.getGoodsConsumes().isEmpty()) {
            return true;
        }
        //套餐物流为空,展示完善按钮
        List<GeneticTestingExpressDeliveryDto> deliveryDtos = result.getDeliveryDtos();
        if (deliveryDtos == null) {
            return true;
        }
        for (GeneticTestingExpressDeliveryDto deliveryDto : deliveryDtos) {
            if (deliveryDto.getExpressCompany() == null || deliveryDto.getRemarks() == null || deliveryDto
                                                                                                       .getCourierDateTime() == null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 补充订单支付信息
     *
     * @param item  PeanutOrderItemDto
     * @param order TestingOrderDto
     */
    private void wrapOrderPayment(PeanutOrderItemDto item, TestingOrderDto order) {
        OrderChargeStatus chargeStatus = StringUtils.isEmpty(order.getChargeStatus()) ? OrderChargeStatus.INIT :
                OrderChargeStatus.getEnum(order.getChargeStatus());
        item.setPaymentState(chargeStatus.getCode());
        if (!checkOrderValid(order)) {
            item.setShowQrCode("0");
            return;
        }

        if (!(OrderChargeStatus.INIT.equals(chargeStatus) || OrderChargeStatus.UNDEFINED.equals(chargeStatus))) {
            item.setShowQrCode("1");
        } else {
            item.setShowQrCode("0");
        }
    }

    /**
     * 补充订单支付信息
     *
     * @param order        订单信息
     * @param orderPayment 支付信息
     */
    private void wrapOrderPayment(GeneticTestingOrder testingOrder, PeanutOrderDto order, GeneticTestingOrderPayment
            orderPayment) {
        OrderChargeStatus chargeStatus = StringUtils.isEmpty(testingOrder.getChargeStatus()) ? OrderChargeStatus.INIT
                : OrderChargeStatus.getEnum(testingOrder.getChargeStatus());
        order.setPaymentState(chargeStatus.getCode());
        if (!checkOrderValid(order)) {
            order.setShowQrCode("0");
            return;
        }

        if (OrderChargeStatus.CONFIRMED.equals(chargeStatus)) {
            order.setShowQrCode("1");
        } else {
            order.setShowQrCode("0");
        }
    }

    /**
     * 这两字段是控制界面是否显示增项费用和经验值的，如果后台套餐中没有配置套餐价格就不展示增项费用，</br>
     * 没有配置经验值就不展示经验值，如果配置了套餐价格但增项费用为0也不展示增项费用，</br>
     * 配置了经验值并且增项费用为0才展示经验值
     *
     * @param result 订单信息
     */
    private void fillOrderAdditionAndExp(PeanutOrderDto result) {
        CalculateCommissionParamDto param = new CalculateCommissionParamDto();
        param.setOrderId(result.getId());
        param.setCaseType(result.getCaseType());
        if (!CollectionUtils.isEmpty(result.getGeneOrderDetails())) {
            param.setPackageIds(result.getGeneOrderDetails().stream().map(PeanutOrderPackageDetailDto::getProductId)
                    .collect(Collectors.toList()));
            OrderCommissionInfo info = calculateCommission(param);
            if (info != null) {
                result.setAdditionValue(info.getAdditionCost() == null ? BigDecimal.ZERO : BigDecimal.valueOf(info
                        .getAdditionCost()));
                if (BigDecimal.ZERO.equals(result.getAdditionValue())) {
                    result.setDifuValue(info.getUserExp() == null ? 0 : info.getUserExp().intValue());
                    if (result.getDifuValue() > 0) {
                        result.setShowExp(true);
                    }
                } else {
                    result.setShowAdditionCost(true);
                }
            }
        }
    }

    /**
     * 上传DCW标志位
     * 0：初始，不可以上传DCW和申请录入，不展示相关操作按钮
     * 1：结束，已经上传了DCW并录入申请，不展示相关操作按钮
     * 2：可以上传DCW和申请录入，展示相关操作按钮
     * null：初始，不可以上传DCW和申请录入，不展示相关操作按钮
     *
     * @param order 订单信息
     * @return 上传DCW标志位
     */
    private String checkRequested(TestingOrderDto order) {
        if (!checkOrderValid(order)) {
            return "0";
        }
        return Integer.valueOf(1).equals(order.getRequested()) ? "1" : "2";
    }

    /**
     * 上传DCW标志位
     * 0：初始，不可以上传DCW和申请录入，不展示相关操作按钮
     * 1：结束，已经上传了DCW并录入申请，不展示相关操作按钮
     * 2：可以上传DCW和申请录入，展示相关操作按钮
     * null：初始，不可以上传DCW和申请录入，不展示相关操作按钮
     *
     * @param order       订单信息
     * @param inputStatus dcw申请录入状态
     * @return 上传DCW标志位
     */
    private String checkRequested(PeanutOrderDto order, DcwApplyInputStatus inputStatus) {
        if (!checkOrderValid(order)) {
            return "0";
        }

        return (DcwApplyInputStatus.APPLIED.equals(inputStatus)
                || DcwApplyInputStatus.ACCEPTED.equals(inputStatus)) ? "1" : "2";
    }

    /**
     * 完善订单标志(0不可完善操作，1可以完善操作)
     *
     * @param order TestingOrderDto
     * @return 完善订单标志
     */
    private String checkNeedSupplyExpress(TestingOrderDto order) {
        OrderStatus currentStatus = OrderStatus.getEnum(order.getStatus());
        return OrderStatus.WAIT_PERFECTED.equals(currentStatus) ? "1" : "0";
    }

    /**
     * 完善订单标志(0不可完善操作，1可以完善操作)
     *
     * @param order TestingOrderDto
     * @return 完善订单标志
     */
    private String needSupplyExpress(TestingOrderDto order) {
        // 已支付支付的订单允许完善
        if (!OrderChargeStatus.CHARGED.equals(OrderChargeStatus.getEnum(order.getChargeStatus()))) {
            return "0";
        }
        // 没有上传样本图片可以允许完善
        if (StringUtils.isBlank(order.getSamplePhoto())) {
            return "1";
        }
        // 套餐没有样本快递信息允许完善
        List<GeneticTestingOrderPackage> packages = orderPackageRepository.queryOrderPackages(order.getId());
        if (!CollectionUtils.isEmpty(packages)) {
            if (packages.stream()
                    .filter(e -> !OrderPackageStatus.END.equals(OrderPackageStatus.getEnum(e.getStatus())))
                    .filter(e -> Integer.valueOf(1).equals(e.getIsStop()))
                    .anyMatch(pack -> StringUtils.isBlank(pack.getCourierCompanyName()))) {
                return "1";
            }
            /*for (GeneticTestingOrderPackage detail : packages) {
                if (Integer.valueOf(1).equals(detail.getIsStop())) {
                    continue;
                }
                if (StringUtils.isBlank(detail.getCourierCompanyName())) {
                    return "1";
                }
            }*/
        }
        // 其它不允许完善
        return "0";
    }

    /**
     * 完善订单标志(0不可完善操作，1可以完善操作)
     *
     * @param order TestingOrderDto
     * @return 完善订单标志
     */
    private String checkNeedSupplyExpress(PeanutOrderDto order) {
        try {
            OrderStatus currentStatus = OrderStatus.getEnum(Integer.valueOf(order.getStatus()));

            return OrderStatus.WAIT_PERFECTED.equals(currentStatus) ? "1" : "0";
        } catch (NumberFormatException e) {
            e.printStackTrace();
            LOGGER.error("订单{}状态{}异常！", order.getId(), order.getStatus());
            throw new IllegalStateException("订单状态异常");
        }
    }

    /**
     * 完善订单标志(0不可完善操作，1可以完善操作)
     *
     * @param order TestingOrderDto
     * @return 完善订单标志
     */
    private String needSupplyExpress(PeanutOrderDto order) {
        // 已支付支付的订单允许完善
        if (!OrderChargeStatus.CHARGED.equals(OrderChargeStatus.getEnum(order.getChargeStatus()))) {
            return "0";
        }
        // 没有上传样本图片可以允许完善
        if (StringUtils.isBlank(order.getSamplePhoto())) {
            return "1";
        }
        // 套餐没有样本快递信息允许完善
        if (!CollectionUtils.isEmpty(order.getGeneOrderDetails())) {
            for (PeanutOrderPackageDetailDto detail : order.getGeneOrderDetails()) {
                if (Integer.valueOf(1).equals(detail.getIsStop())) {
                    continue;
                }
                OrderPackageDetailItemModelDto dto = detail.getGeneOrderDetailItemModel();
                if (dto != null) {
                    if (StringUtils.isBlank(dto.getExpressCompany())) {
                        return "1";
                    }
                } else {
                    return "1";
                }
            }
        }
        // 其它不允许完善
        return "0";
    }

    /**
     * 超过30天未上传申请录入上传DCW警告标志
     *
     * @param order TestingOrderDto
     * @return 上传DCW警告标志
     */
    private String checkNeedWarnRequested(TestingOrderDto order) {
        if (!checkOrderValid(order)) {
            return "0";
        }
        if (order.getRequested() == null || !order.getRequested().equals(1)) {
            LocalDateTime createDateTime = LocalDateTime.ofInstant(order.getCreateDate().toInstant(), ZoneId
                    .systemDefault());
            int durationDays = SimpleDateUtils.durationDays(createDateTime, LocalDateTime.now());

            return durationDays > 30 ? "1" : "0";
        }
        return "0";
    }

    /**
     * 超过30天未上传申请录入上传DCW警告标志
     *
     * @param order TestingOrderDto
     * @return 上传DCW警告标志
     */
    private String checkNeedWarnRequested(PeanutOrderDto order) {
        if (!checkOrderValid(order)) {
            return "0";
        }
        if (order.getRequested() == null || !"1".equals(order.getRequested())) {
            LocalDateTime createDateTime = LocalDateTime.ofInstant(order.getCreateDate().toInstant(), ZoneId
                    .systemDefault());
            long durationSeconds = SimpleDateUtils.durationSeconds(createDateTime, LocalDateTime.now());

            return durationSeconds > needWarnRequestedLimit ? "1" : "0";
        }
        return "0";
    }

    /**
     * 校验是否需要确认签收
     *
     * @param order TestingOrderDto
     * @return 是否需要确认签收
     */
    private String checkNeedConfirmRecieved(TestingOrderDto order) {
        if (!checkOrderValid(order)) {
            return "0";
        }
        if (!OrderStatus.WAIT_DIFU_SIGNING.equals(OrderStatus.getEnum(order.getStatus()))) {
            return "0";
        }

        List<GeneticTestingExpressDelivery> expressDeliveryList = expressDeliveryRepository
                .queryOrderAvailableExpress(order.getId());
        if (CollectionUtils.isEmpty(expressDeliveryList)) {
            return "0";
        }

        return CollectionUtils.isEmpty(expressDeliveryList.stream()
                .filter(e -> OrderStatus.INIT.getValue().equals(e.getStatus()))
                .collect(Collectors.toList()))
                ? "0" : "1";
    }

    /**
     * 校验是否需要确认签收
     *
     * @param order TestingOrderDto
     * @return 是否需要确认签收
     */
    private String checkNeedConfirmRecieved(PeanutOrderDto order) {
        if (!checkOrderValid(order)) {
            return "0";
        }
        try {
            OrderStatus currentStatus = OrderStatus.getEnum(Integer.valueOf(order.getStatus()));
            if (!OrderStatus.WAIT_DIFU_SIGNING.equals(currentStatus)) {
                return "0";
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            LOGGER.error("订单{}状态{}异常！", order.getOrderNo(), order.getStatus());
            return "0";
        }

        List<GeneticTestingExpressDelivery> expressDeliveryList = expressDeliveryRepository
                .queryOrderAvailableExpress(order.getId());
        if (CollectionUtils.isEmpty(expressDeliveryList)) {
            return "0";
        }

        return CollectionUtils.isEmpty(expressDeliveryList.stream()
                .filter(e -> OrderStatus.INIT.getValue().equals(e.getStatus()))
                .collect(Collectors.toList()))
                ? "0" : "1";
    }

    /**
     * 校验订单状态是否有效
     *
     * @param order TestingOrderDto
     * @return 订单状态是否有效
     */
    private boolean checkOrderValid(TestingOrderDto order) {
        OrderStatus orderStatus = OrderStatus.getEnum(order.getStatus());
        return !StringUtils.equals(order.getDeleteFlag().toString(), "1") || orderStatus.isValid();
    }

    /**
     * 校验订单状态是否有效
     *
     * @param order TestingOrderDto
     * @return 订单状态是否有效
     */
    private boolean checkOrderValid(PeanutOrderDto order) {
        try {
            OrderStatus orderStatus = OrderStatus.getEnum(Integer.valueOf(order.getStatus()));
            return !StringUtils.equals(order.getDelFlag(), "1") || orderStatus.isValid();
        } catch (NumberFormatException e) {
            e.printStackTrace();
            LOGGER.error("订单{}状态{}异常！", order.getOrderNo(), order.getStatus());
            return false;
        }
    }

    /**
     * 检查是否有DCW信息
     *
     * @param order TestingOrderDto
     * @return 是否有DCW信息
     */
    private String checkHasDcw(TestingOrderDto order) {
        if (StringUtils.isNotEmpty(order.getDcwFigures())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(order.getYizhuFigures())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(order.getImageFigures())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(order.getMirrorFigures())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(order.getBloodFigures())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(order.getTumorFigures())) {
            return "1";
        }
        return "0";
    }

    /**
     * 检查是否有DCW信息
     *
     * @param dcw TestingOrderDto
     * @return 是否有DCW信息
     */
    private String checkHasDcw(GeneticTestingOrderDcw dcw) {
        if (dcw == null) {
            return "0";
        }
        if (StringUtils.isNotEmpty(dcw.getDcwImagesUrl())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(dcw.getYizhuImagesUrl())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(dcw.getImageInspectionImagesUrl())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(dcw.getMirrorInspectionImagesUrl())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(dcw.getBloodInspectionImagesUrl())) {
            return "1";
        }

        if (StringUtils.isNotEmpty(dcw.getTumorInspectionImagesUrl())) {
            return "1";
        }
        return "0";
    }

    @Override
    public ApiResult<List<DoctorOrderItemDto>> queryDoctorTestingOrder(
            String doctorId, String appStatus, String keyWord, LimitHelper limitHelper) {
        // 设置查询条件
        GeneticTestingOrderCondition condition = new GeneticTestingOrderCondition();
        condition.setDoctorId(doctorId);
        condition.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
        DoctorAppStatus doctorAppStatus = DoctorAppStatus.getEnum(appStatus);
        if (!DoctorAppStatus.ALL.equals(doctorAppStatus)) {
            Optional<String> statuses = doctorAppStatus.getStatuses().stream()
                    .map(e -> String.valueOf(e.getCode()))
                    .reduce((a, b) -> a + "," + b);
            statuses.ifPresent(condition::setStatus);
        }
        condition.setKeywords2(keyWord);
        // 设置排序参数
        OrderHelper orderHelper = OrderHelper.create(GeneticTestingOrderField.CREATE_DATE_TIME.getValue());

        List<TestingOrderDto> orderList = orderRepository.queryConditionOrder(condition, orderHelper, limitHelper);
        if (CollectionUtils.isEmpty(orderList)) {
            return ApiResult.succ();
        }

        return ApiResult.succ(orderList.stream().map(e -> {
            DoctorOrderItemDto item = new DoctorOrderItemDto();
            item.setOrderNo(e.getOrderNo());
            if (e.getTotalCharges() != null) {
                item.setTotalCharges(e.getTotalCharges().floatValue());
            }
            item.setOrderId(e.getId());
            item.setCreateTime(e.getCreateDate());
            OrderStatus orderStatus = OrderStatus.getEnum(e.getStatus());
            item.setStatus(orderStatus.getValue());
            DoctorAppStatus.parseOrderStatus(orderStatus)
                    .ifPresent(s -> item.setAppStatus(s.getValue()));
            item.setTestingPurpose(e.getTestingPurpose());
            item.setPatientName(e.getPatientName());
            return item;
        }).collect(Collectors.toList()));
    }

    @Override
    public ApiResult<PeanutOrderDto> findServantTestingOrder(String groundServantId, String orderId) {
        // 校验地服是否可以查看订单信息
        GeneticTestingOrder testingOrder = orderRepository.findById(orderId);
        if (testingOrder == null || testingOrder.getDeleteFlag() != 0) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(orderId);
        if (addtionA == null || !groundServantId.equals(addtionA.getUserId())) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        // 查询B表和订单修改信息
        GeneticTestingOrderAddtionB addtionB = orderRepository.findAddtionBByOrderId(orderId);
        GeneticTestingOrderInterchange interchange = orderRepository.findHandlingInterchangeByOrderId(orderId);
        // 构建返回结果
        PeanutOrderDto result = buildPeanutOrderDto(testingOrder, addtionA, addtionB, interchange);
        // 查询订单关联物流信息
        List<GeneticTestingExpressDelivery> expressList = expressDeliveryRepository.queryOrderAvailableExpress(orderId);
        result.setExpressModels(buildExpressModelDtoList(expressList));
        // 填充花生仁订单套餐详情
        fillGeneOrderDetails(result);
        // 填充花生仁订单相关耗材信息
        fillGeneOrderGoodsConsumes(result);
        // 查询订单关联支付信息
        GeneticTestingOrderPayment payment = orderPaymentRepository.getLatestPaymentByOrderId(orderId);
        result.setOrderPayment(buildOrderPaymentDto(payment));
        wrapOrderPayment(testingOrder, result, payment);
        // 填充订单DCW信息
        fillOrderDcw(result);
        // 填充检测申请单
        result.setRequisitionList(buildSimpleRequisitionDto(orderId));
        // 填充确认签收标志位
        result.setNeedConfirmRecieved(checkNeedConfirmRecieved(result));
        // 填充完善订单标志位
        result.setNeedSupplyExpress(needSupplyExpress(result));
        // 增项费用与地服经验值
        fillOrderAdditionAndExp(result);
        // todo 原代码中没有相应字段，但API上有
        result.setNeedSupplyAddition(null);
        result.setNeedPayAddition(null);
        return ApiResult.succ(result);
    }

    @Override
    public ApiResult<DoctorOrderDto> findDoctorTestingOrder(String doctorId, String orderId) {
        GeneticTestingOrder testingOrder = orderRepository.findById(orderId);
        if (testingOrder == null || !testingOrder.getDoctorId().equals(doctorId) || testingOrder.getDeleteFlag() != 0) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(testingOrder.getId());
        DoctorOrderDto result = buildDoctorOrderDto(testingOrder, addtionA);
        result.setProducts(buildDoctorOrderPackageDto(testingOrder));
        if (StringUtils.isNotBlank(addtionA.getUserId())) {
            ApiResult<GeneticTestingUserDto> difuResult = geneticUserService.getUserInfo(addtionA.getUserId());
            if (difuResult.isSucc()) {
                SimpleDoctorServantDto difuInfo = new SimpleDoctorServantDto();
                difuInfo.setServiceEngineerMobile(difuResult.getData().getPhone());
                difuInfo.setServiceEngineerName(difuResult.getData().getRealName());
                result.setDifuInfo(difuInfo);
            }
        }

        result.setPatient(buildDoctorOrderPatientDto(testingOrder));
        return ApiResult.succ(result);
    }

    private List<DoctorOrderPackageDto> buildDoctorOrderPackageDto(GeneticTestingOrder testingOrder) {
        List<GeneticTestingOrderPackage> packages = orderPackageRepository.queryOrderPackages(testingOrder.getId());
        if (CollectionUtils.isEmpty(packages)) {
            return null;
        }
        return packages.stream()
                // 排除终止的和变更待确认的套餐
                .filter(e -> !OrderPackageStatus.END.equals(OrderPackageStatus.getEnum(e.getStatus())))
                .filter(e -> !OrderPackageStatus.WAIT_CONFIRM.equals(OrderPackageStatus.getEnum(e.getStatus())))
                .map(e -> {
                    DoctorOrderPackageDto dto = new DoctorOrderPackageDto();
                    dto.setProductId(e.getPackageId());
                    String productName = e.getPackageName();
                    BigDecimal productPrice = e.getCharges();
                    try {
                        if (StringUtils.isBlank(productName) || productPrice == null) {
                            ApiResult<GeneticTestingPackage> packageApiResult = productService.getPackageById(e
                                    .getPackageId(), 1);
                            if (!packageApiResult.isSucc()) {
                                LOGGER.error("获取套餐{}信息失败", e.getPackageId());
                            } else {
                                productName = packageApiResult.getData().getPackageName();
                                productPrice = packageApiResult.getData().getGeneticTestingProduct()
                                        .getDetectionPrice();
                            }
                        }
                    } catch (Exception exception) {
                        LOGGER.error("获取套餐{}信息失败", e.getPackageId());
                        exception.printStackTrace();
                    }
                    dto.setProductName(productName);
                    dto.setProductPrice(productPrice);
                    GeneticTestingOrderPackageDetail detail = orderPackageRepository.findOrderPackageDetail(testingOrder
                            .getId(), e.getPackageId());
                    if (detail != null) {
                        dto.setReportNames(Lists.newArrayList(detail.getReportName()));
                        dto.setReportAuditFlag(detail.getReportAuditFlag());
                    }
                    List<SimpleSpecimenDto> specimenDtos = querySimpleSpecimen(e.getSampleIds());
                    if (!CollectionUtils.isEmpty(specimenDtos)) {
                        dto.setSpecimens(specimenDtos.stream().map(SimpleSpecimenDto::getLabel).collect(Collectors
                                .toList()));
                    }
                    dto.setIsStop(e.getIsStop());
                    dto.setSampleTime(e.getCollectSampleDateTime());
                    dto.setSampleType(e.getSampleType());
                    dto.setOrgName(e.getGeneticTestingAgencyName());

                    return dto;
                }).collect(Collectors.toList());
    }

    private DoctorOrderPatientDto buildDoctorOrderPatientDto(GeneticTestingOrder testingOrder) {
        DoctorOrderPatientDto patient = new DoctorOrderPatientDto();
        patient.setPatientName(testingOrder.getPatientName());
        patient.setPatientPhoneNumber(testingOrder.getPatientPhone());
        patient.setPatientSex(testingOrder.getPatientSex());
        patient.setPatientAge(testingOrder.getPatientAge());
        return patient;
    }

    private DoctorOrderDto buildDoctorOrderDto(GeneticTestingOrder testingOrder, GeneticTestingOrderAddtionA addtionA) {
        DoctorOrderDto result = new DoctorOrderDto();
        result.setOrderId(testingOrder.getId());
        result.setMemberId(testingOrder.getDoctorId());
        result.setOrderNo(testingOrder.getOrderNo());
        result.setTestingPurpose(testingOrder.getTestingPurpose());
        result.setCreateTime(testingOrder.getCreateDateTime());
        result.setRemark(testingOrder.getRemarks());
        result.setTotalCharges(testingOrder.getTotalCharges());
        result.setCancerNames(addtionA.getCancersName());
        OrderStatus currentStatus = OrderStatus.getEnum(testingOrder.getStatus());
        result.setStatus(String.valueOf(currentStatus.getCode()));
        DoctorAppStatus.parseOrderStatus(OrderStatus.getEnum(testingOrder.getStatus()))
                .ifPresent(e -> result.setAppStatus(e.getValue()));
        result.setTestingTime(testingOrder.getTestingDateTime());
        result.setCancelReason(testingOrder.getCancelReason());
        result.setCancelType(testingOrder.getCancelType());
        return result;
    }

    /**
     * 构建订单的检测申请单
     *
     * @param orderId 订单id
     * @return 检测申请单
     */
    private List<SimpleRequisitionDto> buildSimpleRequisitionDto(String orderId) {
        List<GeneticTestingOrderRequisition> requisitions = orderRepository.queryOrderRequisition(orderId);
        if (CollectionUtils.isEmpty(requisitions)) {
            return null;
        }
        return requisitions.stream().map(e -> {
            SimpleRequisitionDto dto = new SimpleRequisitionDto();
            dto.setId(e.getId());
            dto.setCode(e.getRequisitionNo());
            return dto;
        }).collect(Collectors.toList());
    }

    /**
     * 填充订单DCW信息
     *
     * @param result 花生仁订单
     */
    private void fillOrderDcw(PeanutOrderDto result) {
        GeneticTestingOrderDcw dcw = orderRepository.findOrderDcw(result.getId());
        if (dcw != null) {
            result.setDcwId(dcw.getDcwId());
            result.setAllotState(dcw.getAllotStatus());
            result.setDcwFigures(dcw.getDcwImagesUrl());
            String dcwCaseType = dcw.getDcwCaseType();
            if (StringUtils.isNotBlank(dcwCaseType)) {
                DcwCaseType caseType = DcwCaseType.getEnum(Integer.valueOf(dcwCaseType));
                if (caseType != null) {
                    result.setCaseType(caseType.getCode());
                    result.setCaseTypeDictLabel(caseType.getValue());
                }
            }

            DcwApplyInputStatus inputStatus = DcwApplyInputStatus.getEnum(dcw.getApplyInputStatus() == null ? 0 : dcw
                    .getApplyInputStatus());
            result.setDcwStatus(inputStatus.getCode().toString());
            result.setDcwStatusDictLabel(inputStatus.getDcwStatusDesc());
            if (inputStatus.isApplied()) {
                if (StringUtils.isNotBlank(result.getDifuId())) {
                    ApiResult<GeneticTestingUserDto> dcwInputerResult = geneticUserService.getUserInfo(result
                            .getDifuId());
                    if (!dcwInputerResult.isSucc()) {
                        LOGGER.error("获取dcw上传用户{}信息失败！reason：{}", result.getDifuId(), dcwInputerResult.getDesc());
                    } else {
                        GeneticTestingUserDto dcwInputer = dcwInputerResult.getData();
                        if (dcwInputer != null) {
                            result.setDcwInputer(dcwInputer.getRealName());
                        } else {
                            LOGGER.error("获取dcw上传用户{}信息为空！", result.getDifuId());
                        }
                    }
                }
            }

            result.setYizhuFigures(dcw.getYizhuImagesUrl());
            result.setBloodFigures(dcw.getBloodInspectionImagesUrl());
            result.setImageFigures(dcw.getImageInspectionImagesUrl());
            result.setMirrorFigures(dcw.getMirrorInspectionImagesUrl());
            result.setTumorFigures(dcw.getTumorInspectionImagesUrl());
            // 填充DCW相关标志位
            result.setRequested(checkRequested(result, inputStatus));
        } else {
            result.setRequested("0");
        }
        result.setHasDcw(checkHasDcw(dcw));
        result.setNeedWarnRequested(checkNeedWarnRequested(result));
    }

    /**
     * 构建订单花生仁支付信息
     *
     * @param payment 原始订单支付信息
     * @return 花生仁支付信息
     */
    private OrderPaymentDto buildOrderPaymentDto(GeneticTestingOrderPayment payment) {
        if (payment == null) {
            return null;
        }
        OrderPaymentDto dto = new OrderPaymentDto();
        dto.setId(payment.getId());
        dto.setPaymentAmount(payment.getPaymentAmount());
        PaymentChannelType channelType = PaymentChannelType.getEnum(payment.getPaymentChannel() == null ? -1 :
                payment.getPaymentChannel());
        dto.setPaymentChannel(payment.getPaymentChannel());
        dto.setPaymentChannelDictLabel(channelType.getDesc());
        dto.setPaymentDate(payment.getPaymentDateTime());
        dto.setPaymentMethod(payment.getPaymentWay());
        if (payment.getPaymentWay() != null) {
            PayType payType = PayType.getEnum(payment.getPaymentWay());
            dto.setPaymentMethodDictLabel(payType.getDesc());
        }
        dto.setPaymentStatus(payment.getPaymentStatus());
        if (payment.getPaymentStatus() != null) {
            PaymentIntStatus paymentIntStatus = PaymentIntStatus.getEnum(payment.getPaymentStatus());
            dto.setPaymentStatusDictLabel(paymentIntStatus.getDesc());
        }
        dto.setTradeNo(payment.getPaymentNo());
        return dto;
    }

    /**
     * 填充花生仁订单相关耗材信息
     *
     * @param result 花生仁订单
     */
    private void fillGeneOrderGoodsConsumes(PeanutOrderDto result) {
        List<GeneticTestingGoodsConsume> consumes = orderRepository.queryOrderGoodsConsumes(result.getId());
        if (!CollectionUtils.isEmpty(consumes)) {
            Map<String, GeneticGoodsApplyHistory> historyMap = new HashMap<>(16);
            Map<String, GeneticGoods> goodsMap = new HashMap<>(consumes.size());
            // 查询地服用户拥有的耗材信息
            ApiResult<List<GeneticGoodsApplyHistory>> historiesResult = consumablesGoodsService.queryServantGoods
                    (result.getDifuId());
            if (historiesResult.isSucc() && !CollectionUtils.isEmpty(historiesResult.getData())) {
                historiesResult.getData().forEach(e -> historyMap.put(e.getGoodsId(), e));
            }
            // 查询当前使用的耗材信息
            String goodsIds = StringUtils.join(consumes.stream()
                    .map(GeneticTestingGoodsConsume::getGoodsId)
                    .collect(Collectors.toList()), ",");
            ApiResult<List<GeneticGoods>> goodsResult = consumablesGoodsService.queryGeneticGoods(goodsIds);
            if (goodsResult.isSucc() && !CollectionUtils.isEmpty(goodsResult.getData())) {
                goodsResult.getData().forEach(e -> goodsMap.put(e.getId(), e));
            }
            result.setGeneOrderGoodsConsumes(consumes.stream().map(e -> {
                SimpleGoodsConsumeDto consume = new SimpleGoodsConsumeDto();
                consume.setId(e.getId());
                consume.setAmount(e.getAmount());
                consume.setGoodsId(e.getGoodsId());
                if (goodsMap.get(e.getGoodsId()) != null) {
                    consume.setGoodsName(goodsMap.get(e.getGoodsId()).getName());
                }
                if (historyMap.get(e.getGoodsId()) != null) {
                    GeneticGoodsApplyHistory history = historyMap.get(e.getGoodsId());
                    Integer currentNumber = history.getTotalApplyAmount() - history.getTotalUsedAmount();
                    consume.setCurrentNumber(currentNumber > 0 ? currentNumber : 0);
                } else {
                    consume.setCurrentNumber(0);
                }
                return consume;
            }).collect(Collectors.toList()));
        }
    }

    /**
     * 填充花生仁订单套餐详情
     *
     * @param result 花生仁订单套餐详情
     */
    private void fillGeneOrderDetails(PeanutOrderDto result) {
        List<GeneticTestingOrderPackage> packages = orderPackageRepository.queryOrderPackages(result.getId());
        if (!CollectionUtils.isEmpty(packages)) {
            List<PeanutOrderPackageDetailDto> geneOrderDetails = packages.stream()
                    // 排除终止的和变更待确认的套餐
                    .filter(e -> !OrderPackageStatus.END.equals(OrderPackageStatus.getEnum(e.getStatus())))
                    .filter(e -> !OrderPackageStatus.WAIT_CONFIRM.equals(OrderPackageStatus.getEnum(e.getStatus())))
                    .map(e -> {
                        GeneticTestingOrderPackageDetail packageDetail = orderPackageRepository
                                .findOrderPackageDetail(e.getGeneticTestingOrderId(), e.getPackageId());
                        PeanutOrderPackageDetailDto detail = new PeanutOrderPackageDetailDto();
                        detail.setId(e.getId());
                        detail.setOrderId(e.getGeneticTestingOrderId());
                        detail.setProductId(e.getPackageId());
                        detail.setBarcode(e.getBarCode());
                        detail.setCharges(e.getCharges());
                        detail.setCollectDate(e.getCollectSampleDateTime());
                        detail.setCommission(e.getCommission());
                        // 构建套餐关联物流信息
                        detail.setGeneOrderDetailItemModel(buildOrderPackageDetailItemModelDto(e, packageDetail));
                        detail.setIsStop(e.getIsStop());
                        detail.setItemId(e.getCourierNo());
                        detail.setProductDetailId(e.getGeneticTestingAgencyId());
                        detail.setProductName(e.getPackageName());
                        detail.setRemarks(e.getRemarks());
                        detail.setSampleType(e.getSampleType());
                        List<SimpleSpecimenDto> specimens = querySimpleSpecimen(e.getSampleIds());
                        detail.setSpecimenList(specimens);
                        if (!CollectionUtils.isEmpty(specimens)) {
                            specimens.stream()
                                    .map(SimpleSpecimenDto::getLabel)
                                    .reduce((a, b) -> a + "," + b)
                                    .ifPresent(detail::setSampleTypeDictLabel);
                        }
                        detail.setSendWax(e.getIsSendWaxBlock());
                        detail.setSendWaxDictLabel(sendWaxDictLabel(detail.getSendWax()));
                        detail.setTestOrgId(e.getGeneticTestingAgencyId());
                        detail.setTestingOrgName(e.getGeneticTestingAgencyName());
                        // PS：此处因子网-补寄补款情况有所变化
                        if (Integer.valueOf(1).equals(e.getIsSupplementFlag())) {
                            fillInterChangeDetail(detail, e, packageDetail);
                        }

                        detail.setHospitalCode(e.getHospitalCode());
                        detail.setSampleBarcode(e.getSampleBarcode());
                        detail.setWhiteCount(e.getWhiteCount());
                        detail.setStatus(e.getStatus());
                        detail.setOriProductName(e.getOldPackageName());
                        detail.setBloodSampleImages(e.getBloodSampleImages());
                        detail.setSampleId(e.getSampleIds());
                        return detail;
                    }).collect(Collectors.toList());
            result.setGeneOrderDetails(geneOrderDetails);
            geneOrderDetails.stream()
                    .map(PeanutOrderPackageDetailDto::getProductName)
                    .reduce((a, b) -> a + "," + b).ifPresent(result::setProductNames);
        }
    }

    private String sendWaxDictLabel(Integer sendWax) {
        if (sendWax == null) {
            return null;
        }
        if (sendWax == 1) {
            return "未寄回";
        } else if (sendWax == 2) {
            return "已寄回";
        }
        return Strings.EMPTY;
    }

    private List<SimpleSpecimenDto> querySimpleSpecimen(String sampleIds) {
        if (StringUtils.isBlank(sampleIds)) {
            return null;
        }
        ApiResult<List<GeneticTestingSampleDto>> sampleResult = sampleService.getSamplesByIds(sampleIds);
        if (!sampleResult.isSucc()) {
            LOGGER.error("获取关联样本信息失败：" + sampleResult.getDesc());
            return null;
        }
        List<GeneticTestingSampleDto> samples = sampleResult.getData();
        if (CollectionUtils.isEmpty(samples)) {
            LOGGER.warn("没有查询到关联的样本信息");
            return null;
        }
        return samples.stream().map(e -> {
            SimpleSpecimenDto specimen = new SimpleSpecimenDto();
            specimen.setId(e.getId());
            specimen.setLabel(e.getLabel());
            specimen.setLabelKey(e.getLabelKey());
            specimen.setLabelDescription(e.getLabelDescription());
            return specimen;
        }).collect(Collectors.toList());
    }

    /**
     * 构建套餐关联物流信息
     *
     * @param orderPackage  订单套餐信息
     * @param packageDetail 订单套餐详情
     * @return 套餐关联物流信息
     */
    private OrderPackageDetailItemModelDto buildOrderPackageDetailItemModelDto(
            GeneticTestingOrderPackage orderPackage, GeneticTestingOrderPackageDetail packageDetail) {
        OrderPackageDetailItemModelDto itemModelDto = null;
        // 根据是否填写快递公司名称字段来控制套餐关联物流信息是否展示
        if (StringUtils.isNotBlank(orderPackage.getCourierCompanyName())) {
            itemModelDto = new OrderPackageDetailItemModelDto();
            itemModelDto.setId(orderPackage.getId());
            itemModelDto.setDeliverStatus(orderPackage.getDeliverStatus());
            // 标签获取
            itemModelDto.setDeliverStatusDictLabel(orderPackage.getDeliverStatus());
            itemModelDto.setExpressCompany(orderPackage.getCourierCompanyName());
            if (StringUtils.isNotBlank(orderPackage.getCourierCompanyName())) {
                itemModelDto.setExpressCompanyDictLabel(ExpressCompanyType.getEnum(orderPackage.getCourierCompanyName())
                        .getDesc());
            }
            itemModelDto.setExpressNo(orderPackage.getCourierNo());
            itemModelDto.setExpressTime(orderPackage.getCourierDateTime());
            itemModelDto.setRemarks(orderPackage.getCourierRemarks());
            if (packageDetail != null) {
                itemModelDto.setReportName(packageDetail.getReportName());
                itemModelDto.setReportNo(packageDetail.getReportNo());
                itemModelDto.setReportAuditFlag(packageDetail.getReportAuditFlag());
                itemModelDto.setReportUploadTime(packageDetail.getReportUploadDateTime());
            }
        }
        return itemModelDto;
    }

    /**
     * 填充套餐补寄补款信息
     * <p>
     * PS：此处补寄情况有所变化，原大数据平台针对如换套餐产生的样本补寄情况是在原有订单的基础上进行的修改.</br>
     * 而当前因子网是重新是重新生成新订单，复制以前不变的信息，重新记录新的套餐样本信息，就相当于针对当前订单
     * 不存在补寄的说法
     * </p>
     *
     * @param detail
     * @param orderPackage
     * @param orderPackageDetail
     */
    private void fillInterChangeDetail(
            PeanutOrderPackageDetailDto detail, GeneticTestingOrderPackage orderPackage,
            GeneticTestingOrderPackageDetail orderPackageDetail) {
        OrderInterchangeDto interchange = new OrderInterchangeDto();
        interchange.setSupplementFlag(orderPackage.getIsSupplementFlag());
        interchange.setAmount(orderPackage.getSupplementAmount());
        interchange.setCollectDate(orderPackage.getCollectSampleDateTime());
        interchange.setSampleType(orderPackage.getSupplementSampleType());
        interchange.setSampleTypeLabel(orderPackage.getSupplementSampleType());
        interchange.setSampleBarcode(null);
        interchange.setExpressCompany(null);
        interchange.setExpressCompanyLabel(null);
        interchange.setExpressNo(null);
        interchange.setSampleReuse(null);

        interchange.setWhiteCount(orderPackage.getWhiteCount());
        interchange.setSendWax(orderPackage.getIsSendWaxBlock());

        detail.setInterChangeDetail(interchange);
    }

    private List<ExpressModelDto> buildExpressModelDtoList(List<GeneticTestingExpressDelivery> expressList) {
        if (CollectionUtils.isEmpty(expressList)) {
            return null;
        }
        ApiResult<List<SysDictDto>> dictResult = dictService.valueByDictAddtionId("4003");
        Map<String, String> expressTypeMap = new HashMap<>(4);
        if (dictResult.isSucc() && !CollectionUtils.isEmpty(dictResult.getData())) {
            dictResult.getData().forEach(e -> expressTypeMap.put(e.getValue(), e.getLabel()));
        } else {
            LOGGER.error("查询寄送类型字典项错误：{}", dictResult.getDesc());
        }
        return expressList.stream().map(e -> {
            ExpressModelDto model = new ExpressModelDto();
            model.setId(e.getId());
            model.setOrderId(e.getOrderId());
            model.setExist("1");
            model.setSendType(e.getCourierType());
            model.setSendTypeDictLabel(expressTypeMap.get(e.getCourierType()));
            model.setExpressNo(e.getCourierNo());
            model.setStatus(e.getStatus());
            ExpressDeliveryStatus deliveryStatus = ExpressDeliveryStatus.getEnum(e.getStatus());
            model.setStatusDictLabel(deliveryStatus.getDesc());
            model.setExpressCompany(e.getCourierCompanyId());
            model.setExpressCompanyLabel(e.getCourierCompanyName());
            /*if (StringUtils.isNotBlank(e.getCourierCompanyId())) {
                model.setExpressCompanyLabel(ExpressCompanyType.getEnum(e.getCourierCompanyId()).getDesc());
            }*/
            model.setExpressDate(e.getCourierDateTime());
            model.setExpressAddress(e.getDetailAddress());
            model.setMobile(e.getPhone());
            model.setConfirmDate(e.getSigningDateTime());
            model.setDescription(e.getDescription());
            model.setEnds(e.getIsEnds());
            return model;
        }).collect(Collectors.toList());
    }

    /**
     * 构建花生仁订单详情
     *
     * @param testingOrder 订单基础信息
     * @param addtionA     订单A表信息
     * @param addtionB     订单B表信息
     * @param interchange  订单修改信息学
     * @return 花生仁订单详情
     */
    private PeanutOrderDto buildPeanutOrderDto(
            GeneticTestingOrder testingOrder, GeneticTestingOrderAddtionA addtionA,
            GeneticTestingOrderAddtionB addtionB, GeneticTestingOrderInterchange interchange) {
        PeanutOrderDto result = new PeanutOrderDto();
        result.setId(testingOrder.getId());
        result.setOrderNo(testingOrder.getOrderNo());
        // 填充订单基础信息
        result.setChargeStatus(testingOrder.getChargeStatus());
        ApiResult<GeneticTestingUserDto> userResult = geneticUserService.getUserInfo(testingOrder.getCreatorId());
        if (!userResult.isSucc()) {
            LOGGER.error("获取创建者信息出错：", userResult.getDesc());
        } else {
            result.setCreateBy(userResult.getData().getRealName());
        }

        result.setCreateDate(testingOrder.getCreateDateTime());
        result.setDelFlag(testingOrder.getDeleteFlag().toString());
        result.setDeliverStatus(addtionA.getGeneticTestDeliverStatus());
        result.setDescription(testingOrder.getDescription());
        result.setDifuId(addtionA.getUserId());
        result.setFee(testingOrder.getFee());
        result.setFigures(testingOrder.getCourierImagesUrl());
        result.setFullAmount(addtionA.getIsFullPayment());
        result.setPriceRemark(testingOrder.getModifyPriceRemarks());
        result.setReceiveDate(testingOrder.getReceiveDateTime());
        result.setRemarks(testingOrder.getRemarks());
        result.setReportName(testingOrder.getReportName());
        result.setReportStatus(addtionA.getGeneticTestReportStatus());
        result.setRise(testingOrder.getInvoiceTitle());
        result.setSamplePhoto(testingOrder.getCollectSampleImagesUrl());
        String source = testingOrder.getOrderOrigin() == null ? "" : testingOrder.getOrderOrigin().toString();
        result.setSource(source);
        // 订单状态
        OrderStatus currentStatus = OrderStatus.getEnum(testingOrder.getStatus());
        result.setStatus(String.valueOf(currentStatus.getCode()));
        result.setStatusDictLabel(currentStatus.getDesc());
        result.setStopReason(testingOrder.getStopReason());
        result.setTestingPhoto(testingOrder.getTestingImagesUrl());
        result.setTestingTime(testingOrder.getTestingDateTime());
        result.setTotalCharges(testingOrder.getTotalCharges());
        result.setTotalCommission(testingOrder.getTotalCommission());
        result.setApproveTime(addtionA.getSendPointDateTime());
        result.setExpressImgs(testingOrder.getCourierImagesUrl());
        result.setUpdateBy(null);
        result.setUpdateDate(testingOrder.getUpdateDateTime());
        // 填充医生信息
        result.setMemberId(testingOrder.getDoctorId());
        result.setMemberName(testingOrder.getDoctorName());
        // 填充患者信息
        fillPatientInfo(result, testingOrder, addtionA);
        // 填充相关疾病信息
        fillCancers(result, addtionA);
        // 填充补寄基础信息
        fillHasAddtion(result, addtionA);
        // 填充基因检测关联信息
        result.setGeneOrderRelation(buildGeneticOrderRelationDto(addtionB));
        // 构建简要套餐变更信息
        result.setGeneOrderInterChangeModel(buildSimpleOrderInterchangeDto(interchange));
        // 2019-01-04 追加字段返回
        result.setOrderOrigin(testingOrder.getOrderOrigin());
        OrderStatus status = OrderStatus.getEnum(testingOrder.getStatus());
        // 统一详情列表二次完善按钮展示要求
        Boolean flag = status == OrderStatus.PAID_FOR ? checkOrderPackageInfo(testingOrder.getId()) : status.canShowCompleteBtn();
        result.setCanShowCompleteBtn(flag);
        result.setSendPoints(OrderPointSendStatus.getEnum(addtionA.getOrderPointSendStatus()).isPointSent());
        result.setIsClosed(status.isClosed() ? 1 : 0);

        return result;
    }

    /**
     * 填充相关疾病信息
     *
     * @param result   花生仁订单详情
     * @param addtionA 订单A表信息
     */
    private void fillCancers(PeanutOrderDto result, GeneticTestingOrderAddtionA addtionA) {
        result.setCancers(addtionA.getCancersId());
        List<List<CancerModelDto>> cancerModels = Lists.newArrayList();
        List<CancerModelDto> cancerNames = Lists.newArrayList();
        if (StringUtils.isNotBlank(addtionA.getCancersId())) {
            ApiResult<List<DaCancerDto>> cancerResult = medicineService.cancerInfoByParentId(null);
            if (!cancerResult.isSucc()) {
                LOGGER.error("获取疾病信息失败：" + cancerResult.getDesc());
            } else {
                if (CollectionUtils.isEmpty(cancerResult.getData())) {
                    LOGGER.error("没有获取疾病信息");
                } else {
                    Map<String, DaCancerDto> cancerDtoMap = new HashMap<>(cancerResult.getData().size());
                    cancerResult.getData().forEach(e -> cancerDtoMap.put(e.getId(), e));
                    Arrays.asList(addtionA.getCancersId().split(",")).forEach(cancersId -> {
                        DaCancerDto cancer = cancerDtoMap.get(cancersId);
                        if (cancer == null) {
                            LOGGER.warn("没有找到疾病：{}，对应的疾病信息！", cancersId);
                        } else {
                            List<CancerModelDto> itemModels = Lists.newArrayList();
                            CancerModelDto model = new CancerModelDto();
                            model.setId(cancer.getId());
                            model.setName(cancer.getCancerNameCn());
                            if (StringUtils.isNotBlank(cancer.getParentId())) {
                                DaCancerDto parent = cancerDtoMap.get(cancer.getParentId());
                                CancerModelDto parentModel = new CancerModelDto();
                                parentModel.setId(parent.getId());
                                parentModel.setName(parent.getCancerNameCn());
                                itemModels.add(parentModel);
                            }
                            itemModels.add(model);
                            cancerNames.add(model);
                            cancerModels.add(itemModels);
                        }
                    });
                }
            }
        }
        if (!CollectionUtils.isEmpty(cancerModels)) {
            result.setCancerModels(cancerModels);
        }
        if (!CollectionUtils.isEmpty(cancerNames)) {
            result.setCancerNames(cancerNames.stream().map(CancerModelDto::getName).collect(Collectors.joining(",")));
        }
    }

    /**
     * 填充补寄信息
     *
     * @param result   花生仁订单详情
     * @param addtionA 订单A表
     */
    private void fillHasAddtion(PeanutOrderDto result, GeneticTestingOrderAddtionA addtionA) {
        result.setHasAddition(StringUtils.isBlank(addtionA.getReplenishmentNo()) ? 0 : 1);
        result.setAdditionTotalAmount(addtionA.getReplenishmentAmount());
    }

    /**
     * 构建简要套餐变更信息
     *
     * @param interchange 订单变更信息
     * @return 简要套餐变更信息
     */
    private SimpleOrderInterchangeDto buildSimpleOrderInterchangeDto(GeneticTestingOrderInterchange interchange) {
        if (interchange == null) {
            return null;
        }
        SimpleOrderInterchangeDto simpleInterchange = new SimpleOrderInterchangeDto();
        simpleInterchange.setId(interchange.getId());
        simpleInterchange.setRecordNo(interchange.getRecordNo());
        simpleInterchange.setSupplementFlag(interchange.getReplenishmentFlag());
        simpleInterchange.setAmount(interchange.getDifferenceBalance());
        return simpleInterchange;
    }

    /**
     * 构建基因检测关联信息
     *
     * @param addtionB 订单B表
     * @return 基因检测关联信息
     */
    private GeneticOrderRelationDto buildGeneticOrderRelationDto(GeneticTestingOrderAddtionB addtionB) {
        if (addtionB == null) {
            return null;
        }
        GeneticOrderRelationDto orderRelationDto = new GeneticOrderRelationDto();
        orderRelationDto.setBackRemarks(addtionB.getAnnexBackRemarks());
        orderRelationDto.setPastFlag(addtionB.getIsBeforeDoneGeneticTesting());
        orderRelationDto.setPastItem(addtionB.getBeforeDoneGeneticTestingItem());
        orderRelationDto.setPastResult(addtionB.getBeforeDoneGeneticTestingResult());
        orderRelationDto.setPayerType(addtionB.getPayerType());
        orderRelationDto.setDiscount(addtionB.getDiscount());
        orderRelationDto.setTestingApplyType(addtionB.getTestingApplyType());
        orderRelationDto.setPatientConfirmFlag(addtionB.getPatientConfirmFlag());
        orderRelationDto.setPatientConfirmDate(addtionB.getPatientConfirmDateTime());
        return orderRelationDto;
    }

    private void fillPatientInfo(PeanutOrderDto result, GeneticTestingOrder testingOrder, GeneticTestingOrderAddtionA
            addtionA) {
        result.setPatientName(testingOrder.getPatientName());
        result.setPatientPhoneNumber(testingOrder.getPatientPhone());
        if (testingOrder.getPatientSex() != null) {
            result.setSex(testingOrder.getPatientSex().toString());
            result.setSexDictLabel(GenderType.getEnum(testingOrder.getPatientSex()).getDesc());
        }
        result.setAge(testingOrder.getPatientAge());
        result.setCancelReason(testingOrder.getCancelReason());
        result.setPatientFamilyName(testingOrder.getPatientFamilyName());
        result.setPatientFamilyPhoneNumber(testingOrder.getPatientFamilyPhone());
        if (StringUtils.isNotBlank(testingOrder.getTestingPurpose())) {
            result.setTestingPurpose(testingOrder.getTestingPurpose());
            ApiResult<List<SysDictDto>> dictResult = dictService.valueByDictAddtionId("4001");
            if (dictResult.isSucc() && !CollectionUtils.isEmpty(dictResult.getData())) {
                dictResult.getData().stream()
                        .filter(e -> e.getValue().equalsIgnoreCase(testingOrder.getTestingPurpose()))
                        .findFirst()
                        .ifPresent(e -> result.setTestingPurposeDictLabel(e.getLabel()));
            }
        }

        result.setClinical(addtionA.getClinicalDiagnosis());
    }

    /**
     * 支付回调
     *
     * @param paymentNo      支付单号
     * @param paymentAmount  支付金额（单位：元）
     * @param paymentChannel 支付渠道(1-支付宝,2-微信,3-银联)
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String handlePaymentNotice(String paymentNo, BigDecimal paymentAmount, Integer
            paymentChannel) {
        // 支付信息校验检查
        GeneticTestingOrderPayment payment = orderPaymentRepository.findByPaymentNo(paymentNo);
        if (payment == null) {
            return "failed";
        }
        PaymentIntStatus paymentStatus = PaymentIntStatus.getEnum(payment.getPaymentStatus());
        if (!paymentStatus.equals(PaymentIntStatus.INIT) && !paymentStatus.equals(PaymentIntStatus.ON_GOING)) {
            LOGGER.warn("支付单状态异常", paymentNo, payment.getPaymentAmount());
            return "failed";
        }
        // 更新支付信息
        payment.setPaymentStatus(PaymentIntStatus.PAID.getCode());
        // ?1:online,2:offline
        payment.setPaymentWay(1);
        payment.setPaymentChannel(paymentChannel);
        if (!paymentAmount.equals(payment.getPaymentAmount())) {
            LOGGER.error("支付单号[{}]本次接收实际支付金额[{}]与原金额{[]}不符！", paymentNo, paymentAmount, payment.getPaymentAmount());
        }
        payment.setPaymentDateTime(new Date());

        if (payment.getBusinessType() == 1) {
            // 查询更新基因检测订单状态
            GeneticTestingOrder testingOrder = orderRepository.findById(payment.getBusinessId());
            if (testingOrder == null || testingOrder.getDeleteFlag() == 1) {
                LOGGER.error("支付单号[{}]对应的订单[{}]不存在或已删除", paymentNo, payment.getBusinessId());
                return "failed";
            }
            OrderStatus orderStatus = OrderStatus.getEnum(testingOrder.getStatus());
            if (!orderStatus.canPayOnline()) {
                LOGGER.error("用户为订单[{}:{}(不允许支付)]支付了[{} 元]！", testingOrder.getOrderNo(), orderStatus.getDesc(),
                        paymentAmount);
                return "failed";
            }
            if (!paymentAmount.equals(testingOrder.getTotalCharges())) {
                LOGGER.error("支付单号[{}]本次接收实际支付金额[{}]与订单原金额{[]}不符！", paymentNo, paymentAmount, testingOrder
                        .getTotalCharges());
            }
            // 状态变更为：地服收款确认完成（已支付）
            testingOrder.setStatus(OrderStatus.AUDIT_PASS.getCode());
            testingOrder.setChargeStatus("charged");
            testingOrder.setUpdateDateTime(new Date());
            PeanutApiResult result = agencyApplyOrderService.addApplyOrder(testingOrder.getId(), null);
            if (!result.isSuccess() && result.getStatus() != 200) {
                LOGGER.error("订单[{}]支付成功创建检测申请单失败", testingOrder.getOrderNo());
                return "failed";
            }
            orderRepository.updateOrderPaymentStatus(testingOrder);
        }
        orderPaymentRepository.update(payment);
        return "success";
    }

    @Override
    public ApiResult<List<OrderRequisitionDto>> getRequisitionInfoByOrderId(String orderId, String orgIds) {
        FieldChecker.checkEmpty(orderId, "订单id");
        List<GeneticTestingOrderRequisition> requisitionList = orderRequisitionRepository.queryByOrderIdAndOrgId
                (orderId, orgIds);
        if (CollectionUtils.isEmpty(requisitionList)) {
            return ApiResult.succ();
        }
        return ApiResult.succ(requisitionList.stream()
                .map(this::toOrderRequisitionDto)
                .collect(Collectors.toList()));
    }

    /**
     * GeneticTestingOrderRequisition -> OrderRequisitionDto
     *
     * @param requisition GeneticTestingOrderRequisition
     * @return OrderRequisitionDto
     */
    private OrderRequisitionDto toOrderRequisitionDto(GeneticTestingOrderRequisition requisition) {
        OrderRequisitionDto dto = new OrderRequisitionDto();
        dto.setId(requisition.getId());
        dto.setOrgId(requisition.getAgencyId());
        dto.setOrderId(requisition.getOrderId());
        dto.setCode(requisition.getRequisitionNo());
        dto.setData(requisition.getData());
        dto.setStatus(requisition.getRequisitionStatus());
        if (StringUtils.isNotBlank(requisition.getData())) {
            dto.setRequisitionData(JsonUtils.jsonToObject(requisition.getData(), new
                    TypeReference<GeneticRequisitionData>() {
                    }));
        }

        return dto;
    }

    @Override
    public ApiResult<Pagination<OrderInterchangeListDto>> pageInterchange(String groundServantId, int pageNo, int
            pageSize) {
        LimitHelper limitHelper = LimitHelper.create(pageNo, pageSize);
        int totalCount = orderInterchangeRepository.queryInterchangeCount(groundServantId);
        Pagination<OrderInterchangeListDto> pagination = Pagination.newInstance(limitHelper, totalCount);
        if (totalCount > 0) {
            List<OrderInterchangeListDto> interchanges = orderInterchangeRepository.queryOrderInterChangeListDto
                    (groundServantId, limitHelper);
            if (!CollectionUtils.isEmpty(interchanges)) {
                interchanges.forEach(interchange ->
                        interchange.setNeedPayment(checkNeedPayment(interchange))
                );
            }
            pagination.setResult(interchanges);
        }
        return ApiResult.succ(pagination);
    }

    /**
     * 校验是否需要补款
     *
     * @param interchange 订单更换信息
     * @return 是否需要补款（1需要，0不需要）
     */
    private Integer checkNeedPayment(GeneticTestingOrderInterchange interchange) {
        if (ReplenishmentFlagType.ADDITION.getCode().equals(interchange.getReplenishmentFlag())
            && InterchangeStatus.HANDLED.getCode().equals(interchange.getStatus())) {
            return 1;
        }

        return 0;
    }

    /**
     * 校验是否需要补款
     *
     * @param interchange 订单更换信息
     * @return 是否需要补款（1需要，0不需要）
     */
    private Integer checkNeedPayment(OrderInterchangeListDto interchange) {
        if (ReplenishmentFlagType.ADDITION.getCode().equals(interchange.getSupplementFlag())
            && InterchangeStatus.HANDLED.getCode().equals(interchange.getStatus())) {
            return 1;
        }

        return 0;
    }

    @Override
    public ApiResult<OrderInterChangeDetailDto> interChangeInfo(String interchangeId) {
        GeneticTestingOrderInterchange interchange = orderInterchangeRepository.findById(interchangeId);
        if (interchange == null || interchange.getDeleteFlag() == 1) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NOT_EXISTED);
        }
        OrderInterChangeDetailDto result = toOrderInterChangeDetailDto(interchange);
        List<GeneticTestingOrderInterchange> interchanges = orderInterchangeRepository.queryByRecordNo(interchange
                .getRecordNo());
        List<OrderInterChangeDetailItemDto> items = interchanges.stream()
                .map(this::buildInterChangeDetails).collect(Collectors.toList());
        result.setInterChangeDetails(items);

        return ApiResult.succ(result);
    }

    private OrderInterChangeDetailItemDto buildInterChangeDetails(GeneticTestingOrderInterchange interchange) {
        OrderInterChangeDetailItemDto item = new OrderInterChangeDetailItemDto();
        item.setId(interchange.getId());
        item.setOrderId(interchange.getNewOrderId());
        item.setSourceId(interchange.getOldPackageId());
        item.setDestId(interchange.getNewPackageId());

        item.setInterchangeId(interchange.getId());
        item.setAmount(interchange.getDifferenceBalance());
        item.setSupplementFlag(interchange.getReplenishmentFlag());
        item.setRemarks(interchange.getRemarks());
        item.setReason(interchange.getReason());
        item.setActionType(interchange.getActionType());
        item.setProof(interchange.getProof());
        item.setSampleReuse(interchange.getSampleReuse());

        GeneticTestingOrderPackage newPackage = orderPackageRepository.findOrderPackage(interchange.getNewOrderId(),
                interchange.getNewPackageId());
        item.setSpecimen(newPackage.getSampleIds());
        item.setSampleIds(newPackage.getSampleIds());
        item.setSampleType(newPackage.getSampleType());
        if (StringUtils.isNotBlank(newPackage.getGeneticTestingAgencyId())) {
            ApiResult<List<GeneticTestingPackageDetilPeanutDto>> result = productService.getDetailsByPackageId
                    (newPackage.getPackageId());
            if (result.isSucc()) {
                result.getData().stream()
                        .filter(e -> e.getId().equals(newPackage.getGeneticTestingAgencyId()))
                        .findFirst()
                        .ifPresent(e -> {
                            if (!CollectionUtils.isEmpty(e.getSpecimenList())) {
                                List<SimpleSpecimenDto> specimenList = e.getSpecimenList().stream().map(sample -> {
                                    SimpleSpecimenDto specimen = new SimpleSpecimenDto();
                                    specimen.setId(sample.getId());
                                    specimen.setLabel(sample.getLabel());
                                    specimen.setLabelKey(sample.getLabelKey());
                                    specimen.setLabelDescription(sample.getLabelDescription());
                                    return specimen;
                                }).collect(Collectors.toList());
                                item.setSpecimenList(specimenList);
                            }
                        });
            }
        }

        item.setSendWax(newPackage.getIsSendWaxBlock());
        item.setCollectDate(newPackage.getCollectSampleDateTime());
        item.setExpressCompany(newPackage.getCourierCompanyName());
        if (StringUtils.isNotBlank(newPackage.getCourierCompanyName())) {
            item.setExpressCompanyLabel(ExpressCompanyType.getEnum(newPackage.getCourierCompanyName()).getDesc());
        }
        item.setExpressNo(newPackage.getCourierNo());
        item.setExpressTime(newPackage.getCourierDateTime());
        item.setExpressRemark(newPackage.getCourierRemarks());
        item.setSampleBarcode(newPackage.getSampleBarcode());
        item.setBarcode(newPackage.getBarCode());
        item.setHospitalCode(newPackage.getHospitalCode());
        item.setProductName(newPackage.getPackageName());
        item.setOrgName(newPackage.getGeneticTestingAgencyName());
        item.setProductPrice(newPackage.getCharges());
        item.setWhiteCount(newPackage.getWhiteCount());
        item.setBloodSampleImages(newPackage.getBloodSampleImages());
        return item;
    }

    private OrderInterChangeDetailDto toOrderInterChangeDetailDto(GeneticTestingOrderInterchange interchange) {
        OrderInterChangeDetailDto result = new OrderInterChangeDetailDto();
        result.setId(interchange.getId());
        result.setOrderId(interchange.getNewOrderId());
        GeneticTestingOrder order = orderRepository.findById(interchange.getNewOrderId());
        result.setOrderNo(order.getOrderNo());
        result.setRecordNo(interchange.getRecordNo());
        result.setAmount(interchange.getDifferenceBalance());
        result.setSupplementFlag(interchange.getReplenishmentFlag());
        result.setStatus(interchange.getStatus());
        if (interchange.getPayerType() != null) {
            result.setPayerType(interchange.getPayerType().toString());
        }
        result.setNeedPayment(checkNeedPayment(interchange));
        result.setCreateDate(interchange.getCreateDateTime());
        result.setSamplePhoto(interchange.getSampleImageUrl());
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<String> difuPayProcessOrder(TestingOrderRequestDto orderRequest) {
        FieldChecker.checkEmpty(orderRequest, "订单请求信息");
        orderRequest.check();

        String orderId = orderRequest.getTestingOrder().getId();
        GeneticTestingOrder testingOrder = orderRepository.findById(orderId);
        if (testingOrder == null || testingOrder.getDeleteFlag() == 1) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }

        GeneticTestingOrderAddtionB addtionB = orderRepository.findAddtionBByOrderId(testingOrder.getId());
        // 是否需要患者确认：纸质不需要患者确认
        boolean needConfirmed = orderRequest.getTestingOrder().getGeneOrderRelation().needPatientConfirm();
        // 患者是否确认
        boolean patientConfirmed = addtionB != null && addtionB.getPatientConfirmFlag() != null && addtionB
                                                                                                           .getPatientConfirmFlag() == 1;
        // 当需要患者确认，而患者有没有进行确认操作时返回提示
        if (needConfirmed && !patientConfirmed) {
            return ApiResult.fail(OrderErrorCode.CUSTOMER_NOT_CONFIRMED);
        }
        OrderStatus orderStatus = OrderStatus.getEnum(testingOrder.getStatus());
        if (!orderStatus.canPayOnline()) {
            return ApiResult.fail(OrderErrorCode.ORDER_STATUS_EXCEPTION);
        }
        addtionB.setTestingApplyType(orderRequest.getTestingOrder().getGeneOrderRelation().getTestingApplyType());
        addtionB.setPatientConfirmFlag(1);
        addtionB.setPatientConfirmDateTime(new Date());
        orderRepository.updateTestingOrderAddTionB(addtionB);

        GeneticTestingOrderPayment orderPayment = buildGeneticTestingOrderPayment(testingOrder, orderRequest
                .getTestingOrder().getPayMethod());
        testingOrder.setChargeStatus(OrderChargeStatus.INIT.getValue());
        testingOrder.setTestingImagesUrl(orderRequest.getTestingOrder().getTestingPhoto());
        testingOrder.setUpdateDateTime(new Date());
        orderRepository.updateOrderChargeStatus(testingOrder);
        orderPaymentRepository.save(orderPayment);

        String paymentUrl = paymentDomain + "/v1.0/genetic/testing/payment/" + orderPayment.getId();

        return ApiResult.succ(paymentUrl);
    }

    private GeneticTestingOrderPayment buildGeneticTestingOrderPayment(GeneticTestingOrder testingOrder, String
            payMethod) {
        GeneticTestingOrderPayment orderPayment = new GeneticTestingOrderPayment();

        orderPayment.setId(UUID32.randomUUIDString());
        orderPayment.setOrderId(testingOrder.getId());
        orderPayment.setBusinessId(testingOrder.getId());
        orderPayment.setBusinessType(PaymentBusinessType.GENETIC_TESTING.getCode());
        // orderPayment.setPaymentNo(UUID32.randomUUIDString());
        orderPayment.setPaymentWay(PayType.getEnum(payMethod).getValue());
        orderPayment.setPaymentAmount(testingOrder.getTotalCharges());
        orderPayment.setPaymentStatus(PaymentIntStatus.INIT.getCode());
        orderPayment.setUpdateDateTime(new Date());

        return orderPayment;
    }

    private GeneticTestingOrderPayment buildGeneticTestingOrderPayment(
            GeneticTestingOrderInterchange interchange, GeneticTestingOrderAddtionA addtionA, PayType payType) {
        GeneticTestingOrderPayment orderPayment = new GeneticTestingOrderPayment();

        orderPayment.setId(UUID32.randomUUIDString());
        orderPayment.setOrderId(interchange.getNewOrderId());
        orderPayment.setBusinessId(interchange.getId());
        orderPayment.setBusinessType(PaymentBusinessType.GENETIC_TESTING_ADDITION.getCode());
        // orderPayment.setPaymentNo(UUID32.randomUUIDString());
        orderPayment.setPaymentWay(payType.getValue());
        orderPayment.setPaymentAmount(addtionA.getReplenishmentAmount());
        orderPayment.setPaymentStatus(PaymentIntStatus.INIT.getCode());
        orderPayment.setUpdateDateTime(new Date());

        return orderPayment;
    }

    @Override
    public ApiResult<String> interChangeRepaid(String interChangeId, String payMethod) {
        GeneticTestingOrderInterchange interchange = orderRepository.findInterchangeById(interChangeId);
        if (interchange == null || interchange.getDeleteFlag() == 1) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NOT_EXISTED);
        }
        /*if (!(Integer.valueOf(1).equals(interchange.getReplenishmentFlag())
                && Integer.valueOf(0).equals(interchange.getStatus()))) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_REPAID_NO_NEED);
        }*/
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(interchange.getNewOrderId());
        if (addtionA == null
            || Integer.valueOf(0).equals(addtionA.getIsReplenishment())
            || addtionA.getReplenishmentAmount() == null) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_REPAID_NO_NEED);
        }

        PayType payType = PayType.getEnum(payMethod);
        if (interchange.getPayerType() != null) {
            PayerType payerType = PayerType.getEnum(interchange.getPayerType());
            // 当套餐变更处理时选择的是患者支付，则更改支付方式选择为二维码扫码支付
            if (PayerType.PATIENT.equals(payerType)) {
                payType = PayType.CHINAUMS_QR;
            }
        }

        GeneticTestingOrderPayment orderPayment = buildGeneticTestingOrderPayment(interchange, addtionA, payType);
        orderPaymentRepository.save(orderPayment);
        String paymentUrl = paymentDomain + "/v1.0/genetic/testing/payment/" + orderPayment.getId();

        return ApiResult.succ(paymentUrl);
    }

    /**
     * @param id 订单id
     * @return void
     * @description 根据订单id确认患者信息
     * @author maodi
     * @createDate 2018/10/8 11:18
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public void updatePatientInfoConfirm(String id) {
        orderRepository.updatePatientInfoConfirm(id, new Date());
    }

    /**
     * @param orderNo 订单号
     * @return com.hsgene.order.domain.disease.GeneOrder
     * @description 获取患者确认信息
     * @author maodi
     * @createDate 2018/9/30 15:43
     */
    @Override
    public GeneOrder getPatientInfoConfirmByOrderNo(String orderNo) {
        return orderRepository.getPatientInfoConfirmByOrderNo(orderNo);
    }

    /**
     * @param id 订单id
     * @return java.lang.String
     * @description 根据订单id获取患者电话
     * @author maodi
     * @createDate 2018/9/30 16:00
     */
    @Override
    public String getPatientPhoneById(String id) {
        return orderRepository.getPatientPhoneById(id);
    }

    @Override
    public String getTestItemsByOrderNo(String orderNo) {
        return orderRepository.getTestItemsByOrderNo(orderNo);
    }

    /**
     * 校验订单状态
     *
     * @param orderId 订单id
     * @param status  订单状态
     * @return
     */
    @Override
    public Integer checkOrderStatus(String orderId, Integer status) {
        return orderRepository.checkOrderStatus(orderId, status);
    }

    /**
     * 校验医生id
     *
     * @param orderId
     * @return
     */
    @Override
    public String checkDoctorInfo(String orderId) {
        return orderRepository.checkDoctorInfo(orderId);
    }

    /**
     * 获取套餐物流
     *
     * @param orderId   订单id
     * @param productId 套餐id
     * @return
     */
    @Override
    public OrderProductLogisticsInfoDto getOrderProductLogistics(String orderId, String productId) {
        //校验套餐物流是否存在
        return orderRepository.getLogisticsNoAndCompany(orderId, productId);
    }

    /**
     * 获取订单物流
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public List<OrderLogisticsInfoDto> getLogisticsDetail(String orderId) {
        return orderRepository.getLogisticsDetail(orderId);
    }

    @Override
    public ApiResult<String> queryOrderPackageReport(String doctorId, String reportName) {
        FieldChecker.checkEmpty(doctorId, "医生id");
        FieldChecker.checkEmpty(reportName, "报告名称");

        GeneticTestingOrderPackageDetail detail = orderPackageRepository.queryOrderPackageReport(doctorId, reportName);
        if (detail == null || StringUtils.isBlank(detail.getReportUrl())) {
            return ApiResult.fail(OrderErrorCode.ORDER_REPORT_NOT_EXISTED);
        }
        String certificateUrl = QiniuCertificateUtil.getDownloadCertificateStr(detail.getReportUrl());
        if (StringUtils.isBlank(certificateUrl)) {
            LOGGER.error("检测报告加签失败");
            return ApiResult.fail(OrderErrorCode.ORDER_REPORT_NOT_EXISTED);
        }
        int index = certificateUrl.lastIndexOf("/");
        // 缓存报告信息
        String token = UUID32.randomUUIDString();
        redisTemplate.opsForValue().set(reportCacheKey + ":" + token, certificateUrl.substring(index + 1),
                reportCacheExpireSeconds,
                TimeUnit.SECONDS);
        String previewUrl = String.format(reportDomain, token);

        return ApiResult.succ(previewUrl);
    }

    @Override
    public Map<String, List<CommonDictDto>> queryDict(ClientType clientType, String type) {
        Map<String, List<CommonDictDto>> typeDictMap = Maps.newHashMap();
        Arrays.stream(type.split(",")).forEach(e -> {
            Function<ClientType, List<CommonDictDto>> function = orderDictQueryHandleMap.get(e);
            typeDictMap.put(e, function == null ? null : function.apply(clientType));
        });
        return typeDictMap;
    }

    /**
     * 查询dcw信息
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public DcwImageModel getDcwInfos(String orderId) {
        return orderRepository.getDcwInfos(orderId);
    }

    /**
     * 校验样本类型所填参数
     *
     * @param sampleId 样本id
     * @return
     */
    @Override
    public String checkParamsIsNull(String sampleId) {
        return orderRepository.checkParamsIsNull(sampleId);
    }

    /**
     * 订单操作记录
     *
     * @param geneticOrderOperationDetail
     * @return
     * @author jcl
     * @date 2018/11/13 9:54
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void orderOperationLog(GeneticOrderOperationDetail geneticOrderOperationDetail) {
        ApiResult<GeneratorDto> generator = generatorService.getGenerator("order_operation_log", null);
        geneticOrderOperationDetail.setId(generator.getData().getSerialNumber());
        geneticOrderOperationDetail.setOperationDateTime(new Date());
        geneticOrderOperationDetail.setDeleteFlag(0);
        orderRepository.orderOperationLog(geneticOrderOperationDetail);
    }

    /**
     * 校验发放积分
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public Integer checkPointSend(String orderId) {
        return orderRepository.checkPointSend(orderId);
    }

    /**
     * 判断积分是否发放
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public Integer checkPointSendStatus(String orderId) {
        return orderRepository.checkPointSendStatus(orderId);
    }

    /**
     * 发放积分
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 3600, rollbackFor =
            Exception.class)
    public Boolean sendPoint(String orderId) {
        //获取订单医生、地服、经验值、患者信息
        Map<String, Object> map = orderRepository.getSendPointInfo(orderId);
        //审核发放积分tag
        map.put("tagType", verifyIntegralTag);
        if (map.isEmpty()) {
            LOGGER.error("订单[{}]积分发放失败：医生、地服、经验值、患者信息为空", orderId);
            return false;
        }
        ApiResult sendResult = mqService.sendMQ(map);
        if (!sendResult.isSucc()) {
            LOGGER.error("订单[{}]积分发放失败：" + sendResult.getDesc(), orderId);
            return false;
        }
        Date date = new Date();
        //积分状态改为已申请状态
        orderRepository.updatePointStatus(orderId, date);
        //积分存入医生账户
        orderRepository.saveUserPoint(String.valueOf(map.get("difuId")), date, (Integer) map.get("docotorExperience"));
        return true;
    }

    /**
     * 地服发货
     *
     * @param expressDelivery
     * @return
     * @author FX
     * @date 2018/11/14 11:32
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 3600, rollbackFor =
            Exception.class)
    public ApiResult groundDelivery(GeneticTestingExpressDelivery expressDelivery) {
        expressDelivery.check();
        //检验订单状态
        GeneticTestingOrder byId = orderRepository.findById(expressDelivery.getOrderId());
        if (!byId.getStatus().equals(OrderStatus.WAIT_SHIP.getCode())) {
            return ApiResult.fail(OrderErrorCode.ORDER_STATUS_EXCEPTION);
        }
        ApiResult<GeneratorDto> generator = generatorService.getGenerator(null, null);
        if (!generator.isSucc()) {
            return ApiResult.fail(generator.getError());
        }
        expressDelivery.setId(generator.getData().getSerialNumber());
        expressDelivery.setCourierDateTime(new Date());
        orderRepository.groundDelivery(expressDelivery);
        //订单状态变为待收货
        orderRepository.updateTestingOrderStatus(expressDelivery.getOrderId(), OrderStatus.WAIT_RECEIPT_GOODS.getCode
                (), new Date());
        return ApiResult.succ();
    }

    private List<CommonDictDto> queryOrderStatus(ClientType clientType) {
        return Arrays.stream(OrderStatus.values())
                .filter(status -> !(status.equals(OrderStatus.PRE_AUDIT_PASS)
                                    || status.equals(OrderStatus.PRE_AUDIT_FAIL)
                                    || status.equals(OrderStatus.DIFU_COMPLETED)
                                    || status.equals(OrderStatus.AUDIT_PASS)
                                    || status.equals(OrderStatus.SAMPLE_CONFIRMED)
                                    || status.equals(OrderStatus.RECEIVE_PAYMENT_CONFIRMED)
                                    || status.equals(OrderStatus.REPORTED)
                                    || status.equals(OrderStatus.APPLY_BILL)
                                    || status.equals(OrderStatus.STOP)
                                    || status.equals(OrderStatus.ORDER_INIT)
                                    || status.equals(OrderStatus.ORDER_CHARGED)
                                    || status.equals(OrderStatus.ORDER_CONFIRMED)
                                    || status.equals(OrderStatus.UNDEFINED)))
                .map(status -> {
                    CommonDictDto item = new CommonDictDto();
                    item.setValue(String.valueOf(status.getCode()));
                    item.setLabel(status.getDesc());
                    return item;
                }).collect(Collectors.toList());
    }

    private List<CommonDictDto> querySupportedExpressCompany(ClientType clientType) {
        ApiResult<List<SysDictDto>> dictResult = dictService.valueByDictAddtionId("2000");
        if (!dictResult.isSucc()) {
            LOGGER.error("查询寄送类型字典项错误：{}", dictResult.getDesc());
            return Lists.newArrayList();
        }
        return buildDictList(clientType, dictResult.getData());
    }

    private List<CommonDictDto> queryMoleculeTestPurpose(ClientType clientType) {
        ApiResult<List<SysDictDto>> dictResult = dictService.valueByDictAddtionId("4001");
        if (!dictResult.isSucc()) {
            LOGGER.error("查询检测目的字典项错误：{}", dictResult.getDesc());
            return Lists.newArrayList();
        }
        return buildDictList(clientType, dictResult.getData());
    }

    private List<CommonDictDto> queryGeneCaseType(ClientType clientType) {
        return Arrays.stream(DcwCaseType.values())
                .filter(e -> DcwCaseType.COMMON.equals(e) || DcwCaseType.URGENT.equals(e))
                .map(status -> {
                    CommonDictDto item = new CommonDictDto();
                    item.setValue(String.valueOf(status.getCode()));
                    item.setLabel(status.getValue());
                    return item;
                })
                .sorted(Comparator.comparing(CommonDictDto::getValue))
                .collect(Collectors.toList());
    }

    private List<CommonDictDto> buildDictList(ClientType clientType, List<SysDictDto> data) {
        return data.stream()
                .map(e -> {
                    CommonDictDto item = new CommonDictDto();
                    item.setValue(e.getValue());
                    item.setLabel(e.getLabel());
                    return item;
                }).sorted(Comparator.comparing(CommonDictDto::getValue))
                .collect(Collectors.toList());
    }

    /**
     * @param orderNo 订单编号
     * @return com.hsgene.order.domain.v1.GeneticTestingOrder
     * @description 根据订单编号查询订单
     * @author maodi
     * @createDate 2018/11/13 14:25
     */
    @Override
    public GeneticTestingOrder findByOrderNo(String orderNo) {
        return orderRepository.findByOrderNo(orderNo);
    }

    /**
     * @param orderId 订单id
     * @return void
     * @description 更新主订单为待发货
     * @author maodi
     * @createDate 2018/11/13 16:18
     */
    @Override
    public void updateMainOrderDelivery(String orderId) {
        orderRepository.updateMainOrderDelivery(orderId, new Date());
    }

    /**
     * @param orderId 订单id
     * @param userId  用户id
     * @return void
     * @description 订单奖励标记状态改为已奖励，修改更新时间，修改A表更新时间
     * @author maodi
     * @createDate 2018/11/26 15:04
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public void awarded(String orderId, String userId) {
        Date date = new Date();
        orderRepository.updateFirstSingleAwardTo2(date, orderId);
        orderRepository.updateAUpdateDateTime(date, orderId);
        //保存操作记录
        GeneticOrderOperationDetail orderOperationDetail = new GeneticOrderOperationDetail();
        orderOperationDetail.setOrderId(orderId);
        orderOperationDetail.setOperatorId(userId);
        Integer status = orderRepository.getOrderStatusByOrderId(orderId);
        orderOperationDetail.setStatus(status);
        orderOperationDetail.setDescription("订单奖励标记状态改为已奖励");
        orderOperationDetail.setOrderType(1);
        orderOperationLog(orderOperationDetail);
    }

    /**
     * @param orderId 订单id
     * @return com.hsgene.order.dto.console.OrderUpdateRealPriceDto
     * @description 根据订单id查询修改实际价格信息
     * @author maodi
     * @createDate 2018/11/28 10:44
     */
    @Override
    public OrderUpdateRealPriceDto queryUpdateRealPriceDto(String orderId) {
        return orderRepository.queryUpdateRealPriceDto(orderId);
    }

    /**
     * @param orderId        订单id
     * @param packageCharges 套餐价格字符串数组
     * @param realCharges    订单套餐实际价格字符串数组
     * @param packageIds     套餐id数组
     * @param userId         用户id
     * @return
     * @description 修改订单套餐实际价格
     * @author maodi
     * @createDate 2018/11/28 10:46
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public void updatePackageCharges(String orderId, String[] packageCharges, String[] realCharges, String[]
            packageIds, String userId) {
        Date date = new Date();
        Boolean notSet = true;
        int count = 0;
        for (String realChargeStr : realCharges) {
            Double realCharge = Double.valueOf(realChargeStr);
            if (notSet) {
                Double packageCharge = Double.valueOf(packageCharges[count]);
                if (realCharge < packageCharge) {
                    SignDto signDto = new SignDto();
                    signDto.setDoctorVal(0.00);
                    signDto.setGroundVal(0.00);
                    consoleOrderRepository.updateOrderASign(signDto, orderId);
                    notSet = false;
                }
            }
            orderRepository.updatePackageCharges(realCharge, packageIds[count], orderId);
            count++;
        }
        //如果套餐价格都不小于原来的套餐价格就设置为原来的经验值
        if (notSet) {
            String caseType = orderRepository.getCaseTypeByOrderId(orderId);
            calculateVal(Arrays.asList(packageIds), caseType, orderId);
        }
        orderRepository.updateOrderUpdateDateTime(date, orderId);
        //保存操作记录
        GeneticOrderOperationDetail orderOperationDetail = new GeneticOrderOperationDetail();
        orderOperationDetail.setOrderId(orderId);
        orderOperationDetail.setOperatorId(userId);
        Integer status = orderRepository.getOrderStatusByOrderId(orderId);
        orderOperationDetail.setStatus(status);
        orderOperationDetail.setDescription("修改订单套餐实际价格");
        orderOperationDetail.setOrderType(1);
        orderOperationLog(orderOperationDetail);
    }

    /**
     * @param orderId 订单id
     * @return java.lang.Integer
     * @description 根据订单id查询订单来源
     * @author maodi
     * @createDate 2018/11/28 11:10
     */
    @Override
    public Integer queryOrderOrigin(String orderId) {
        return orderRepository.queryOrderOrigin(orderId);
    }

    /**
     * @param dto 订单信息
     * @return com.hsgene.common.util.result.ApiResult
     * @description 花生仁确认订单
     * @author maodi
     * @createDate 2018/12/19 14:06
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public ApiResult peanutConfirmOrder(PeanutCreateAndConfirmOrderDto dto) {
        String orderId = dto.getOrderId();
        Integer origin = orderRepository.queryOrderOrigin(orderId);
        if (ClientType.PEANUT.getCode().equals(origin) || ClientType.GOLD_COLORED_GLASS.getCode().equals(origin)) {
            Double totalCharges = dto.getTotalCharges();
            String patientName = dto.getPatientName();
            Integer payType = dto.getPayerType();
            Date date = new Date();
            orderRepository.confirmOrderFromPG(totalCharges, patientName, date, OrderStatus.WAIT_RECEIPT_MONEY
                    .getCode(), orderId);
            orderRepository.confirmBOrderFromPG(totalCharges, payType, orderId);
            String orderNo = orderRepository.getOrderNoById(orderId);
            String memberId = orderRepository.getUserIdById(orderId);
            CompleteOrderResultInfo resultInfo = new CompleteOrderResultInfo(orderId, orderNo, totalCharges
                    .floatValue(), memberId);
            // 花生仁确认金琉璃订单，当做创建，发送订单创建消息
            sendOrderCreateMessage(orderNo);
            return ApiResult.succ(resultInfo, "花生仁确认订单成功");
        } else {
            return ApiResult.fail(OrderErrorCode.ORDER_ORIGIN_MUST_BE_PEANUT_OR_GOLD_COLORED_GLASS);
        }
    }

    /**
     * @param dto 订单信息
     * @return com.hsgene.common.util.result.ApiResult
     * @description 花生仁下单
     * @author maodi
     * @createDate 2018/12/19 14:06
     */
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
            Exception.class)
    @Override
    public ApiResult peanutCreateOrder(PeanutCreateAndConfirmOrderDto dto) {
        String orderNo = getOrderNo(GeneratorEnum.MEDI.getType());
        String orderId = getUUID32().replaceAll("-", "");
        String aId = getUUID32().replaceAll("-", "");
        String bId = getUUID32().replaceAll("-", "");
        Double totalCharges = dto.getTotalCharges();
        String memberId = dto.getMemberId();
        Date date = new Date();
        orderRepository.createOrderFromPG(orderId, orderNo, totalCharges, dto.getPatientName(), OrderStatus
                .WAIT_RECEIPT_MONEY.getCode(), ClientType.PEANUT.getCode(), memberId, date, 0);
        orderRepository.createAOrderFromPG(aId, orderId, memberId, date);
        orderRepository.createBOrderFromPG(bId, orderId, totalCharges, dto.getPayerType());
        CompleteOrderResultInfo resultInfo = new CompleteOrderResultInfo(orderId, orderNo, totalCharges.floatValue(),
                memberId);
        // 发送订单创建消息
        sendOrderCreateMessage(orderNo);
        return ApiResult.succ(resultInfo, "花生仁下单成功");
    }

    /**
     * 发送订单创建消息
     *
     * @param orderNo 订单编号
     */
    private void sendOrderCreateMessage(String orderNo) {
        byte[] data = orderNo.getBytes();
        // 发送订单30分钟未支付提醒消息
        Message nonePaidMessage = new Message(orderMQTopic, orderNonePaidMQTag, data);
        nonePaidMessage.setStartDeliverTime(System.currentTimeMillis() + ORDER_CREATION_NONE_PAID_TIME);
        nonePaidMessage.setKey("nonePaid-" + UUID32.randomUUIDString());
        SendResult nonePaidSendResult = producer.send(nonePaidMessage);
        LOGGER.info("订单[{}]30分钟未支付提醒消息发送成功！SendResult = {}", orderNo, nonePaidSendResult);


        // 发送订单1小时未支付关闭消息
        Message autoCloseMessage = new Message(orderMQTopic, orderAutoCloseMQTag, data);
        autoCloseMessage.setStartDeliverTime(System.currentTimeMillis() + ORDER_AUTO_CLOSE_TIME);
        autoCloseMessage.setKey("autoClose-" + UUID32.randomUUIDString());
        SendResult autoCloseSendResult = producer.send(autoCloseMessage);
        LOGGER.info("订单[{}]1小时未支付关闭消息发送成功！SendResult = {}", orderNo, autoCloseSendResult);
    }

    @Override
    public ApiResult<NullObject> handleOrderNonePaidMsg(String orderNo) {
        FieldChecker.checkEmpty(orderNo, "订单编号");
        GeneticTestingOrder order = orderRepository.findByOrderNo(orderNo);
        if (order == null) {
            LOGGER.error("订单[{}]不存在，无法发送未支付提醒", orderNo);
            return ApiResult.succ();
        }
        OrderStatus currentStatus = OrderStatus.getEnum(order.getStatus());
        if (!OrderStatus.WAIT_RECEIPT_MONEY.equals(currentStatus)) {
            LOGGER.info("订单[{}]当前状态为[{}:{}]，无需发送未支付提醒", orderNo, currentStatus.getCode(), currentStatus.getDesc());
            return ApiResult.succ();
        }
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(order.getId());
        if (addtionA == null) {
            LOGGER.error("订单[{}]附加A表信息不存在，无法发送未支付提醒", orderNo);
            return ApiResult.succ();
        }
        String content = "您有未付款的基因检测订单，将于30分钟后关闭，查看详情！";
        String title = "基因检测未付款订单提醒";
        PushInfo pushInfo = new PushInfo(title, content, order.getId(), "9", "1");
        ApiResult<String> notifyResult = notificationService.pushNotification(pushInfo, addtionA.getUserId(), false);
        if (!notifyResult.isSucc()) {
            return ApiResult.fail(notifyResult.getError());
        }
        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> handleOrderAutoCloseMsg(String orderNo) {
        FieldChecker.checkEmpty(orderNo, "订单编号");
        GeneticTestingOrder order = orderRepository.findByOrderNo(orderNo);
        if (order == null) {
            LOGGER.error("订单[{}]不存在", orderNo);
            return ApiResult.succ();
        }
        OrderStatus currentStatus = OrderStatus.getEnum(order.getStatus());
        if (!OrderStatus.WAIT_RECEIPT_MONEY.equals(currentStatus)) {
            LOGGER.info("订单[{}]当前状态为[{}:{}]，不能自动关闭", orderNo, currentStatus.getCode(), currentStatus.getDesc());
            return ApiResult.succ();
        }
        order.setStatus(OrderStatus.ORDER_CLOSE.getCode());
        order.setBeforeExceptionStatus(currentStatus.getCode());
        order.setUpdateDateTime(new Date());
        orderRepository.autoCloseOrder(order);

        return ApiResult.succ();
    }

    /**
     * 判断订单是否支付
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public Integer checkOrderIsPay(String orderId) {
        return orderRepository.checkOrderIsPay(orderId);
    }

    /**
     * 患者付款之后确认订单
     *
     * @param confirmedInfo 确认信息
     */
    @Override
    public void updateOrderTestInfo(PatientConfirmedInfo confirmedInfo) {
        orderRepository.updateOrderTestInfo(confirmedInfo);
    }

    /**
     * 删除订单
     *
     * @param orderId 订单id
     */
    @Override
    public void deleteOrderId(String orderId) {
        orderRepository.deleteOrderId(orderId);
    }

    @Override
    public Integer getOrderSource(String orderId) {
        return orderRepository.getOrderPlatform(orderId);
    }

    /**
     * 获取pdf信息
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public List<GeneTestPdfInfo> getTestPdf(String orderId) {
        List<GeneTestPdfInfo> pdfInfos = orderRepository.getTestPdf(orderId);
        //将图片获取七牛
        if (pdfInfos == null) {
            return new ArrayList<>();
        }
        for (GeneTestPdfInfo pdfInfo : pdfInfos) {
            String images = pdfInfo.getPdfImagesUrl();
            if (StringUtils.isEmpty(images)) {
                continue;
            }
            pdfInfo.setPdfImagesUrl(QiniuCertificateUtil.getDownloadCertificateStr(images));
        }
        return pdfInfos;
    }

    /**
     * 获取患者展示信息
     *
     * @param orderId 订单id或者是订单编号
     * @return
     */
    @Override
    public GeneticTestPatientShowInfo getOrderDetailsByOrderId(String orderId) {
        //如果参数是订单编号则需要通过订单编号查询出订单id
        String id = orderRepository.getIdByOrderNo(orderId);
        if (StringUtils.isNotEmpty(id)) {
            orderId = id;
        }
        GeneticTestPatientShowInfo showInfo = orderRepository.getOrderDetailsByOrderId(orderId);
        if (showInfo == null) {
            return null;
        }
        showInfo.setStatusLabel(OrderStatus.getEnum(showInfo.getStatus()).getDesc());
        return showInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<String> completeInterchange(GeneOrderInterchange interchange, String difuId) {
        FieldChecker.checkEmpty(interchange, "变更处理信息");
        interchange.check();
        FieldChecker.checkEmpty(difuId, "地服id");

        // 订单信息校验
        GeneticTestingOrder order = orderRepository.findById(interchange.getOrderId());
        if (order == null || DeleteFlagType.DELETE.equals(DeleteFlagType.getEnum(order.getDeleteFlag()))) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        GeneticTestingOrderAddtionA addtionA = orderRepository.findAddtionAByOrderId(interchange.getOrderId());
        if (addtionA == null) {
            return ApiResult.fail(OrderErrorCode.ORDER_NOT_EXISTED);
        }
        if (!Integer.valueOf(0).equals(addtionA.getPackageChangeFlag())) {
            return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NONE_PERMISSION);
        }
        if (Integer.valueOf(1).equals(addtionA.getIsReplenishment())) {
            FieldChecker.checkEmpty(interchange.getPayerType(), "付款人类型");
        }
        Date updateTime = new Date();
        List<GeneticTestingOrderPackage> packageUpdateList = Lists.newArrayList();
        List<GeneticTestingOrderInterchange> interchangeUpdateList = Lists.newArrayList();
        // 处理套餐变更
        for (GeneOrderInterChangeDetail detail : interchange.getInterChangeDetails()) {
            // 获取变更记录原始信息、变更对应的订单信息、变更对应的套餐信息
            GeneticTestingOrderInterchange originInterchange = orderInterchangeRepository.findById(detail.getId());
            if (originInterchange == null
                || originInterchange.getDeleteFlag() == 1
                || !originInterchange.getNewOrderId().equals(interchange.getOrderId())) {
                return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_NOT_EXISTED);
            }
            GeneticTestingOrderPackage newPackage = orderPackageRepository.findOrderPackage(order.getId(),
                    originInterchange.getNewPackageId());
            if (newPackage == null) {
                return ApiResult.fail(OrderErrorCode.ORDER_PACKAGE_NOT_EXISTED);
            }
            // 状态,0初始,1已处理,2处理完成(补款退款完成)，初始状态才允许进行变更处理
            if (originInterchange.getStatus() != 0) {
                return ApiResult.fail(OrderErrorCode.ORDER_INTERCHANGE_STATUS_EXCEPTION);
            }
            // 当存在待补差额时，需要校验付款人字段
            if (originInterchange.getDifferenceBalance() != null
                && originInterchange.getDifferenceBalance().compareTo(BigDecimal.ZERO) > 0) {
                FieldChecker.checkEmpty(interchange.getPayerType(), "付款人类型");
                originInterchange.setPayerType(Integer.valueOf(interchange.getPayerType()));
            }
            originInterchange.setSampleImageUrl(interchange.getSamplePhoto());
            originInterchange.setSampleReuse(detail.getSampleReuse());
            // 查询原始套餐信息
            GeneticTestingOrderPackage oldPackage = orderPackageRepository.findOrderPackage(originInterchange
                    .getNewOrderId(), originInterchange.getOldPackageId());
            if (oldPackage == null) {
                return ApiResult.fail(OrderErrorCode.ORDER_ORIGIN_PACKAGE_NOT_EXISTED);
            }

            ActionType actionType = ActionType.getEnum(originInterchange.getActionType());
            if (!actionType.needSupplementAmount()) {
                // 不需要补款的直接标记新套餐已确认
                newPackage.setPackageConfirmFlag(1);
                // 终止原有套餐，从变更待确认 -> 终止
                oldPackage.setStatus(OrderPackageStatus.END.getCode());
            }
            // 更新套餐补寄补款信息
            if (actionType.needSupplementSample()) {
                if (Integer.valueOf(1).equals(detail.getSampleReuse())) {
                    newPackage.setSampleBarcode(oldPackage.getSampleBarcode());
                    newPackage.setSampleIds(oldPackage.getSampleIds());
                    newPackage.setSampleType(oldPackage.getSampleType());
                    newPackage.setSupplementSampleType(oldPackage.getSampleType());
                    newPackage.setCourierCompanyName(oldPackage.getCourierCompanyName());
                    newPackage.setCourierNo(oldPackage.getCourierNo());
                    newPackage.setCourierDateTime(oldPackage.getCourierDateTime());
                    newPackage.setCollectSampleDateTime(oldPackage.getCollectSampleDateTime());
                    newPackage.setCourierRemarks(oldPackage.getCourierRemarks());
                    newPackage.setIsSendWaxBlock(oldPackage.getIsSendWaxBlock());
                    newPackage.setHospitalCode(oldPackage.getHospitalCode());
                    newPackage.setSampleBarcode(oldPackage.getSampleBarcode());
                    newPackage.setWhiteCount(oldPackage.getWhiteCount());
                    newPackage.setBloodSampleImages(oldPackage.getBloodSampleImages());
                    newPackage.setSupplementStatus(2);
                } else {
                    // 字段校验
                    FieldChecker.checkEmpty(detail.getSampleIds(), "样本信息");
                    FieldChecker.checkEmpty(detail.getSampleType(), "样本信息");
                    FieldChecker.checkEmpty(detail.getExpressCompany(), "快递信息");
                    FieldChecker.checkEmpty(detail.getExpressTime(), "快递时间");
                    FieldChecker.checkEmpty(detail.getCollectDate(), "采样时间");
                    FieldChecker.checkEmpty(detail.getSampleBarcode(), "样本条码");
                    // 校验样本条码是否重复
                    Integer exist = orderRepository.checkSampleBarCodeIsExists(detail.getSampleBarcode(),
                            originInterchange.getOldOrderId());
                    if (exist != null) {
                        return ApiResult.fail(OrderErrorCode.SAMPLE_BARCODE_IS_EXISTS);
                    }
                    newPackage.setSampleBarcode(detail.getSampleBarcode());

                    ApiResult<List<GeneticTestingSampleDto>> sampleResult = sampleService.getSamplesByIds(detail
                            .getSampleIds());
                    if (!sampleResult.isSucc()) {
                        return ApiResult.fail(sampleResult.getError());
                    } else if (CollectionUtils.isEmpty(sampleResult.getData())) {
                        return ApiResult.fail(OrderErrorCode.SAMPLE_ID_NOT_EXISTED);
                    }
                    for (GeneticTestingSampleDto dto : sampleResult.getData()) {
                        if (StringUtils.isNotBlank(dto.getParentLabelKey())) {
                            for (String s : dto.getParentLabelKey().split(",")) {
                                if ("1".equals(s)) {
                                    FieldChecker.checkMinValue(detail.getWhiteCount(), 1, "白片数量");
                                } else if ("2".equals(s)) {
                                    FieldChecker.checkEmpty(detail.getHospitalCode(), "医院编码");
                                } else if ("3".equals(s)) {
                                    FieldChecker.checkEmpty(detail.getSendWax(), "是否寄回余蜡");
                                } else if ("4".equals(s)) {
                                    FieldChecker.checkEmpty(detail.getBloodSampleImages(), "血液样本图片");
                                }
                            }
                        }
                    }
                    newPackage.setSampleIds(detail.getSampleIds());
                    newPackage.setSampleType(detail.getSampleType());
                    newPackage.setSupplementSampleType(detail.getSampleType());
                    newPackage.setCourierCompanyName(detail.getExpressCompany());
                    newPackage.setCourierNo(detail.getExpressNo());
                    newPackage.setCourierDateTime(detail.getExpressTime());
                    newPackage.setCollectSampleDateTime(detail.getCollectDate());
                    newPackage.setCourierRemarks(detail.getExpressRemark());

                    newPackage.setIsSendWaxBlock(detail.getSendWax());
                    newPackage.setHospitalCode(detail.getHospitalCode());
                    newPackage.setSampleBarcode(detail.getSampleBarcode());
                    newPackage.setWhiteCount(detail.getWhiteCount());
                    newPackage.setBloodSampleImages(detail.getBloodSampleImages());
                    newPackage.setSupplementStatus(1);
                }
            }
            packageUpdateList.add(oldPackage);
            packageUpdateList.add(newPackage);
            interchangeUpdateList.add(originInterchange);
        }
        // 更新订单样本图片
        order.setUpdateDateTime(updateTime);
        if (StringUtils.isNotBlank(order.getCollectSampleImagesUrl())) {
            order.setCollectSampleImagesUrl(order.getCollectSampleImagesUrl() + "," + interchange.getSamplePhoto());
        } else {
            order.setCollectSampleImagesUrl(interchange.getSamplePhoto());
        }
        orderRepository.updateOrderForInterchange(order);

        if (!CollectionUtils.isEmpty(interchange.getGeneOrderGoodsConsumes())) {
            List<GeneticOrderGoodsInfoDto> goodsInfoDtos = interchange.getGeneOrderGoodsConsumes().stream()
                    .map(e -> {
                        GeneticOrderGoodsInfoDto info = new GeneticOrderGoodsInfoDto();
                        info.setGoodsId(e.getGoodsId());
                        info.setAmount(e.getAmount());
                        return info;
                    }).collect(Collectors.toList());
            //插入新耗材
            orderRepository.insertOrderGoodsConsume(goodsInfoDtos, order.getId(), updateTime);
            //更新申请历史genetic_goods_apply_history表
            orderRepository.updateGoodsApplyHistory(goodsInfoDtos, difuId, updateTime);
        }
        // 是否需要补款
        String paymentUrl = null;
        if (Integer.valueOf(1).equals(addtionA.getIsReplenishment())) {
            GeneticTestingOrderPayment orderPayment = new GeneticTestingOrderPayment();
            orderPayment.setId(UUID32.randomUUIDString());
            orderPayment.setOrderId(order.getId());
            orderPayment.setBusinessId(interchange.getId());
            orderPayment.setBusinessType(PaymentBusinessType.GENETIC_TESTING_ADDITION.getCode());
            PayerType payerType = PayerType.getEnum(Integer.valueOf(interchange.getPayerType()));
            PayType payType = PayerType.DIFU.equals(payerType) ? PayType.ALIPAY_MOBILE : PayType.CHINAUMS_QR;
            orderPayment.setPaymentWay(payType.getValue());
            orderPayment.setPaymentAmount(addtionA.getReplenishmentAmount());
            orderPayment.setPaymentStatus(PaymentIntStatus.INIT.getCode());
            orderPayment.setUpdateDateTime(new Date());
            orderPaymentRepository.save(orderPayment);
            // 更新当前变更记录信息
            interchangeUpdateList.forEach(e -> {
                e.setStatus(1);
            });
            if ("1".equals(interchange.getPayerType())) {
                paymentUrl = paymentDomain + "/v1.0/genetic/testing/payment/" + orderPayment.getId();
            }
        } else {
            // 更新当前变更记录信息
            interchangeUpdateList.forEach(e -> {
                e.setStatus(2);
            });
            addtionA.setUpdateDateTime(updateTime);
            addtionA.setPackageChangeFlag(1);
            // 后台在操作套餐变更时就已经生成申请单，不需要再次生成
        }
        interchangeUpdateList.forEach(e -> {
            orderInterchangeRepository.update(e);
        });
        // todo 优化
        packageUpdateList.forEach(newPackage -> {
            orderPackageRepository.updateForInterchange(newPackage);
        });
        orderRepository.updateAdditionAForInterchange(addtionA);

        return ApiResult.succ(paymentUrl);
    }

    /**
     * @param orderId 订单id
     * @return com.hsgene.order.domain.v1.GeneticTestingOrder
     * @description 根据订单id查找订单信息
     * @author maodi
     * @createDate 2019/1/17 10:02
     */
    @Override
    public GeneticTestingOrder findById(String orderId) {
        return orderRepository.findById(orderId);
    }

    /**
     * 校验状态是否有效
     *
     * @param orderId 订单id
     * @param status  状态值
     * @return
     */
    @Override
    public Integer checkOrderStatusIsEffect(String orderId, Integer... status) {
        return orderRepository.checkOrderStatusIsEffect(orderId, status);
    }

    /**
     * 判断订单是否标记
     *
     * @param orderId 订单id
     * @return
     */
    @Override
    public Integer checkOrderIsSign(String orderId) {
        return orderRepository.checkOrderIsSign(orderId);
    }

    /**
     * @param orderId 订单id
     * @return java.lang.Integer
     * @description 校验订单状态是否在待地管确认、待确认样本、报告待上传、报告待审核状态之间
     * @author maodi
     * @createDate 2019/1/28 14:19
     */
    @Override
    public Integer checkSecondPerfectOrderStatus(String orderId) {
        return orderRepository.checkSecondPerfectOrderStatus(orderId);
    }

    /**
     * @param packageIdList 套餐id链表
     * @param caseType      订单病例类型
     * @param orderId       订单id
     * @return void
     * @description 计算地服和医生经验值
     * @author maodi
     * @createDate 2019/1/31 15:01
     */
    private void calculateVal(List<String> packageIdList, String caseType, String orderId) {
        List<ProductInfoDto> productList = orderRepository.getProductInfoByPackageIds(packageIdList);
        Double totalCommission = 0.00d;
        Double totalDoctorVal = 0.00d;
        Double totalGroundVal = 0.00d;
        for (ProductInfoDto productInfoDto : productList) {
            if (productInfoDto != null) {
                Double commission = productInfoDto.getCommission();
                totalCommission += commission;
                Double doctorVal = 0.00d;
                Double groundVal = 0.00d;
                if (CaseType.CONVENTIONAL_CASES.getCode().toString().equals(caseType)) {
                    Integer commonDoctorVal = productInfoDto.getCommonDoctorVal();
                    doctorVal = commonDoctorVal == null ? 0.00d : commonDoctorVal.doubleValue();
                    Integer commonGroundVal = productInfoDto.getCommonGroundVal();
                    groundVal = commonGroundVal == null ? 0.00d : commonGroundVal.doubleValue();
                } else if (CaseType.URGENT_CASE.getCode().toString().equals(caseType)) {
                    Integer urgentDoctorVal = productInfoDto.getUrgentDoctorVal();
                    doctorVal = urgentDoctorVal == null ? 0.00d : urgentDoctorVal.doubleValue();
                    Integer urgentGroundVal = productInfoDto.getUrgentGroundVal();
                    groundVal = urgentGroundVal == null ? 0.00d : urgentGroundVal.doubleValue();
                }
                totalDoctorVal += commission * doctorVal;
                totalGroundVal += commission * groundVal;
            }
        }
        SignDto signDto = new SignDto();
        Double doctorVal = totalCommission <= 0 ? 0 : (Double)(totalDoctorVal / totalCommission);
        Double groundVal = totalCommission <= 0 ? 0 : (Double)(totalGroundVal / totalCommission);
        signDto.setDoctorVal(doctorVal);
        signDto.setGroundVal(groundVal);
        consoleOrderRepository.updateOrderASign(signDto, orderId);
    }

    /**
     * @param orderId 订单id
     * @return java.lang.String
     * @description 获取订单快递图片
     * @author maodi
     * @createDate 2019/2/20 13:42
     */
    @Override
    public String selectCourierImagesUrl(String orderId) {
        return orderRepository.selectCourierImagesUrl(orderId);
    }

    /**
     * @param orderId 订单id
     * @return
     * @description 查询订单快递公司是否为空
     * @author maodi
     * @createDate 2019/2/20 14:05
     */
    @Override
    public List<String> selectCourierCompanyName(String orderId) {
        return orderRepository.selectCourierCompanyName(orderId);
    }

    /**
     * @param orderId 订单id
     * @return com.hsgene.order.dto.peanut.OrderCheckInfoDto
     * @description 快递回单、样本图片是否为空
     * @author maodi
     * @createDate 2019/2/20 16:51
     */
    @Override
    public OrderCheckInfoDto checkOrderSample(String orderId) {
        return orderRepository.checkOrderSample(orderId);
    }

    /**
     * @param orderId 订单id
     * @return com.hsgene.order.dto.peanut.OrderCheckInfoDto
     * @description 验证快递公司，快递时间，快递备注，快递单号是否为空
     * @author maodi
     * @createDate 2019/2/20 16:51
     */
    @Override
    public OrderCheckInfoDto checkPackageDeliver(String orderId) {
        return orderRepository.checkPackageDeliver(orderId);
    }
}